Лучше ли использовать корневой регистратор или именованный логгер в Python

Я пытаюсь понять, как лучше использовать logging в python для нескольких модулей. Я вижу здесь http://docs.python.org/2/howto/logging#logging-from-multiple-modules о том, как использовать корневой журнал для регистрации нескольких модулей. Как видно из ссылки, вы не можете определить, откуда в вашем приложении появляются ваши сообщения, поскольку все они отображают имя "root".

Мне кажется, что есть два варианта (это предполагает, что мои модули НЕ находятся в структуре пакета, а представляют собой всего лишь группу модулей в одной папке):

1) Используйте корневой журнал, как в примере, но измените форматирование журнала, чтобы включить имя файла:

# myapp.py
import logging
import mylib

def main():
    logging.basicConfig(format='%(asctime)s %(filename)s %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  #filename='myapp.log', 
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()

#mylib.py
import logging

def do_something():
    logging.info('Do something')




In [4]: import myapp

In [5]: myapp.main()
03/06/2014 12:22:07 PM myapp.py INFO: Started
03/06/2014 12:22:07 PM mylib.py INFO: Do something
03/06/2014 12:22:07 PM myapp.py INFO: Finished

2) Используйте корневой регистратор в главном приложении, но именованный логгер в подмодулях, и используйте "имя" вместо "filename" в формате журнала:

# myapp.py
import logging
import mylib

def main():
    #logging.basicConfig(format='%(asctime)s %(filename)s %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  #filename='myapp.log', 
    logging.basicConfig(format='%(asctime)s %(name)s %(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  #filename='myapp.log', 
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()

#mylib.py
import logging

def do_something():
    #logging.info('Do something')
    logger = logging.getLogger(__name__)
    logger.info('Do something')



In [3]: import myapp

In [4]: myapp.main()
03/06/2014 12:27:29 PM root INFO: Started
03/06/2014 12:27:29 PM mylib INFO: Do something
03/06/2014 12:27:29 PM root INFO: Finished

Ответ 1

Vinay Sajip (сторонник модуля регистрации) делает здесь рекомендацию, которая аналогична вашей опции №2, за исключением того, что вы можете использовать именованный логгер всюду, даже в myapp:

import logging
import mylib
logger = logging.getLogger(__name__)

def main():
    logging.basicConfig(format='%(asctime)s %(module)s %(levelname)s: %(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p', level=logging.INFO)  
    logger.info('Started')
    mylib.do_something()
    logger.info('Finished')

if __name__ == '__main__':
    main()

что дает

03/06/2014 12:59:25 PM myapp INFO: Started
03/06/2014 12:59:25 PM mylib INFO: Do something
03/06/2014 12:59:25 PM myapp INFO: Finished

Обратите внимание, что если вы используете %(module)s вместо %(name)s, вы получите myapp, где вы получили root или myapp.py, или __main__.

Эта симметрия - всегда используется logger - может быть особенно полезна, если myapp иногда называют script и иногда импортируется как модуль.