#python #logging
#python #ведение журнала
Вопрос:
У меня простая настройка ведения журнала:
def main()
# ....
# Create logger
logging.basicConfig(filemode='w', level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# Create file handler for DEBUG and above
fh1 = logging.FileHandler(__name__ '.debug.log')
fh1.setLevel(logging.DEBUG)
# Create file handler for INFO and above
fh2 = logging.FileHandler(__name__ '.info.log')
fh2.setLevel(logging.INFO)
# Create console handler with INFO and above
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# Add all the handlers to the logger
logger.addHandler(fh1)
logger.addHandler(fh2)
logger.addHandler(ch)
# ....
Затем, когда я вызываю
logger.info("this is an INFO message")
logger.debug("this is a DEBUG message")
Я получаю следующее на консоли:
this is an INFO message
INFO:__main__:this is an INFO message
this is a DEBUG message
DEBUG:__main__:this is a DEBUG message
Хотя я ожидал видеть только INFO
сообщения в консоли (поскольку я указал logging.info
выше для StreamHandler
). Почему я получаю эти дубликаты?
Мои .debug.log
и info.log
файлы содержат только сообщения на правильном уровне, но их форматирование не включает в себя префиксы INFO:__main__
ни DEBUG:__main__
. Почему их форматирование отличается?
Комментарии:
1. зачем устанавливать level =DEBUG, я всегда использую
logging.basicConfig(format='%(asctime)s %(message)s')
Также имейте в виду, что экземпляры logger являются одноэлементными, поэтому, возможно, установка 2 обработчиков заставляет его повторять сообщения на 2 уровнях: INFO и DEBUG.
Ответ №1:
logging.basicConfig(filemode='w', level=logging.DEBUG)
создает StreamHandler
. Итак, ваш код создает два StreamHandlers
, один с уровнем ведения журнала DEBUG
, а другой с уровнем INFO
.
basicConfig
это удобная функция. Если вы хотите создать свои собственные обработчики, вызывать их не обязательно basicConfig
. (Или вы можете вызвать basicConfig
и добавить дополнительные обработчики …)
Если вы не указываете имя файла при вызове basicConfig
, то в корневой регистратор добавляется StreamHandler
. Это код внутри basicConfig
функции:
if handlers is None:
filename = kwargs.get("filename")
if filename:
mode = kwargs.get("filemode", 'a')
h = FileHandler(filename, mode)
else:
stream = kwargs.get("stream")
h = StreamHandler(stream)