Эффективный способ настройки ведения журнала через модуль пакета

У меня есть пакет, в котором есть несколько компонентов, которые могли бы выиграть от использования ведения журнала и вывода полезной информации.

То, что я не хочу делать, это "настроить" правильное ведение журнала для каждого отдельного файла где-то вдоль этих строк:

import logging
logging.basicConfig(level=DEBUG)
my_function = logging.getLogger("my_function")
my_class = logging.getLogger("my_class")

Я пробовал несколько подходов, один из которых добавлял код шаблона в класс внутри модуля утилиты и пытался сделать что-то вроде этого:

from util import setlogging
set_logging()

Но даже указанное выше решение не выглядит чистым для меня и вызовет проблемы, потому что setLogger не имеет метода __call__. Мне понравилось то, что мой класс "set_logging" читал бы форму конфигурационного файла и имел бы значения по умолчанию, поэтому неважно, какой уровень или какой тип формата ведения журнала я хотел бы правильно настроить.

Есть ли способ инициализировать правильное ведение журнала по всей доске в моем пакете? Может быть, в файле __init__.py?

И чтобы быть как можно более подробным, это то, что setlogging (теперь функция, а не класс) выглядит следующим образом:

def setlogging(config=None):
    if config == None:
        config = config_options() # sets default values
    levels = {
        'debug': DEBUG,
       'info': INFO
        }

    level = levels.get(config['log_level'])
    log_format = config['log_format']
    datefmt = config['log_datefmt']

    basicConfig(
        level   = level,
        format  = log_format,
        datefmt = datefmt)

Ответ 1

Если вы хотите, чтобы весь код в различных модулях вашего пакета использовал один и тот же объект журнала, вам просто нужно (сделать этот регистратор доступным - см. позже - и) позвонить

mylogger.warning("Attenzione!")

или тому подобное, а не logging.warning & c. Таким образом, проблема сводится к созданию одного объекта mylogger для всего пакета и обеспечения его доступности во всех модулях в пакете. (В качестве альтернативы вы могли использовать именованные логиторы с именами, начинающимися с имени пакета, за которым следует точка, но в то время как это очень часть функциональности пакета logging, я лично никогда не нашел его естественным способом работы).

Итак, вашей функции util.setlogging можно просто следовать, скажем,

mylogger = logging.getLogger(package_name)

и каждый модуль, который импортирует util, может просто использовать

util.mylogger.warning('Watch out!')

и тому подобное. Это, по-моему, самый простой подход, пока применяется понятие, что все код в пакете должен регистрироваться одинаковым образом.

Ответ 2

Правильный способ использования модуля для ведения журнала -

import logging
logger = logging.getLogger('my_module_name')

и

logger.debug('help!')

становится no-op, пока кто-то не называет logging.basicConfig() (или вариант).