Python Logging - отключить ведение журнала из импортированных модулей
Я использую модуль протоколирования Python и хотел бы отключить сообщения журнала, напечатанные сторонними модулями, которые я импортирую. Например, я использую что-то вроде следующего:
logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)
Это выводит мои отладочные сообщения, когда я делаю logger.debug( "мое сообщение!" ), но также выводит отладочные сообщения из любого импортируемого модуля (например, запросы и ряд других вещей).
Я хотел бы видеть только сообщения журнала из модулей, которые меня интересуют. Возможно ли сделать этот модуль регистрации?
В идеале я бы хотел, чтобы логгер мог печатать сообщения из "ModuleX, ModuleY" и игнорировать все остальные.
Я просмотрел следующее, но я не хочу отключать/разрешать ведение журнала перед каждым вызовом импортированной функции:
logging - как игнорировать журналы импортированных модулей?
Ответы
Ответ 1
Проблема в том, что вызов getLogger
без аргументов возвращает корневой регистратор, поэтому, когда вы устанавливаете уровень logging.DEBUG
, вы также устанавливаете уровень для других модулей, которые используют этот регистратор.
Вы можете решить эту проблему, просто не используя root logger. Для этого просто передайте имя в качестве аргумента, например, имя вашего модуля:
logger = logging.getLogger('my_module_name')
# as before
это создаст новый регистратор и, таким образом, не приведет к непреднамеренному изменению уровня ведения журнала для других модулей.
Очевидно, вы должны использовать logger.debug
вместо logging.debug
, поскольку последняя является вспомогательной функцией, которая вызывает метод debug
корневого регистратора.
Это упоминается в Расширенном руководстве по ведению журналов. Это также позволяет вам легко узнать, какой модуль вызвал сообщение журнала.
Ответ 2
Если вы собираетесь использовать пакет python logging
, это обычное соглашение для определения регистратора в каждом модуле, который его использует.
logger = logging.getLogger(__name__)
Многие популярные пакеты python делают это, включая requests
. Если пакет использует это соглашение, легко включить/отключить ведение журнала для него, поскольку имя регистратора будет иметь то же имя, что и пакет (или будет дочерним для этого регистратора). Вы даже можете зарегистрировать его в том же файле, что и другие ваши регистраторы.
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
requests_logger = logging.getLogger('requests')
requests_logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
requests_logger.addHandler(handler)
Ответ 3
Не уверен, что это уместно для публикации, но я застрял в течение длительного времени & хотел выручить кого-нибудь с той же самой проблемой, поскольку я нигде не нашел это!
Я получал журналы отладки от matplotlib, несмотря на то, что следовал довольно простой документации в расширенном руководстве по журналированию
и устранение неполадок. Я запускал свой регистратор в main()
одного файла и импортировал функцию для создания графика из другого файла (куда я импортировал matplotlib).
Для меня работало задание уровня matplotlib до его импорта, а не после, как это было для других модулей в моем основном файле. Это показалось мне нелогичным, поэтому, если у кого-то есть понимание того, как вы можете установить конфигурацию для регистратора, который еще не был импортирован, мне было бы интересно узнать, как это работает. Спасибо!
В моем основном файле:
import logging
import requests
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logging.getLogger('requests').setLevel(logging.DEBUG)
def main():
...
В моем файле plot.py
:
import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
import matplotlib.pyplot as plt
def generatePlot():
...
Ответ 4
@Бакуриу довольно элегантно объясняет эту функцию. И наоборот, вы можете использовать метод getLogger()
для извлечения и перенастройки/отключения нежелательных журналов.
Я также хотел добавить метод logging.fileConfig()
, который принимает параметр с именем disable_existing_loggers
, который отключит любые ранее установленные регистраторы (т.е. в импортированных модулях).
Ответ 5
Это отключает все существующие регистраторы, такие как созданные импортированными модулями, при этом все еще используется корневой журнал (и без необходимости загрузки внешнего файла).
logging.config.dictConfig({
'version': 1,
'disable_existing_loggers': True,
})
Обратите внимание, что вам нужно импортировать все модули, которые вы не хотите регистрировать в первую очередь! В противном случае они не будут считаться "существующими регистраторами". Затем он отключит все регистраторы из этих модулей. Это может привести к тому, что вы также упустите важные ошибки!
Более подробные примеры с использованием связанных параметров конфигурации см. в https://gist.github.com/st4lk/6287746 и здесь является (частично работающим) примером, использующим YAML для конфигурации с библиотекой coloredlog
.
Ответ 6
Вы можете использовать что-то вроде:
logging.getLogger("imported_module").setLevel(logging.WARNING)
logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)
Это установит для моего собственного уровня журнала модуля значение DEBUG, при этом импортированный модуль не сможет использовать тот же уровень.
Примечание:
"imported_module"
можно заменить на imported_module.__name__
(без кавычек), а "my_own_logger_name"
можно заменить на __name__
, если вы предпочитаете это делать.