Подтвердить что ты не робот

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 - как игнорировать журналы импортированных модулей?

4b9b3361

Ответ 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__, если вы предпочитаете это делать.