Введение в Python Logging
Этот модуль определяет функции и классы, которые реализуют гибкую систему регистрации событий для приложений и библиотек.
Основное преимущество API ведения журнала, предоставляемого стандартным библиотечным модулем, заключается в том, что все модули Python могут участвовать в ведении журнала, поэтому журнал вашего приложения может содержать ваши собственные сообщения, интегрированные с сообщениями от сторонних модулей.
Итак, начнем:
Пример конфигурации прямо в коде
import logging
logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.debug('this is a %s test', 'debug')
Пример вывода:
2016-07-26 18:53:55,332 root DEBUG this is a debug test
Пример конфигурации через INI-файл
Предполагая, что файл называется logging_config.ini. Подробнее для формата файла находятся в конфигурации протоколирования раздела лесозаготовительного учебника .
[loggers]
keys=root
[handlers]
keys=stream_handler
[formatters]
keys=formatter
[logger_root]
level=DEBUG
handlers=stream_handler
[handler_stream_handler]
class=StreamHandler
level=DEBUG
formatter=formatter
args=(sys.stderr,)
[formatter_formatter]
format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s
Затем используйте logging.config.fileConfig()
в коде:
import logging
from logging.config import fileConfig
fileConfig('logging_config.ini')
logger = logging.getLogger()
logger.debug('often makes a very good meal of %s', 'visiting tourists')
Пример конфигурации через словарь
Начиная с Python 2.7, вы можете использовать словарь с деталями конфигурации. PEP 391 содержит перечень обязательных и факультативных элементов в словаре конфигурации.
import logging
from logging.config import dictConfig
logging_config = dict(
version = 1,
formatters = {
'f': {'format':
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
},
handlers = {
'h': {'class': 'logging.StreamHandler',
'formatter': 'f',
'level': logging.DEBUG}
},
root = {
'handlers': ['h'],
'level': logging.DEBUG,
},
)
dictConfig(logging_config)
logger = logging.getLogger()
logger.debug('often makes a very good meal of %s', 'visiting tourists')
Регистрация исключений
Если вы хотите , чтобы войти исключения вы можете и должны использовать logging.exception(msg)
метод:
>>> import logging
>>> logging.basicConfig()
>>> try:
... raise Exception('foo')
... except:
... logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: foo
Не передавайте исключение в качестве аргумента:
Как logging.exception(msg)
ожидает msg
ARG, это распространенная ошибка , чтобы передать исключение в лесозаготовительном вызов , как это:
>>> try:
... raise Exception('foo')
... except Exception as e:
... logging.exception(e)
...
ERROR:root:foo
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: foo
Хотя на первый взгляд может показаться, что это правильно, на самом деле это проблематично из-за причины, по которой исключения и различные кодировки работают вместе в модуле регистрации:
>>> try:
... raise Exception(u'föö')
... except Exception as e:
... logging.exception(e)
...
Traceback (most recent call last):
File "/.../python2.7/logging/__init__.py", line 861, in emit
msg = self.format(record)
File "/.../python2.7/logging/__init__.py", line 734, in format
return fmt.format(record)
File "/.../python2.7/logging/__init__.py", line 469, in format
s = self._fmt % record.__dict__
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)
Logged from file <stdin>, line 4
Попытка войти исключение , которое содержит юникод символы, таким образом , будет с треском провалились.Он скроет StackTrace первоначального исключения путем переопределения его новое, которое возникает в процессе форматирования вашего logging.exception(e)
вызова.
Очевидно, что в вашем собственном коде вы можете знать о кодировке в исключениях. Однако сторонние библиотеки могут справиться с этим по-другому.
Правильное использование:
Если вместо исключения вы просто передадите сообщение и дадите Python свою магию, он будет работать:
>>> try:
... raise Exception(u'föö')
... except Exception as e:
... logging.exception('bar')
...
ERROR:root:bar
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6
Как вы можете видеть , что мы на самом деле не использовать e
в том случае, вызов logging.exception(...)
волшебно форматирует самый последнее исключение.
Регистрация исключений с уровнями журнала, не являющимися ошибками
Если вы хотите , чтобы войти исключение с другим уровнем журнала , чем ошибка, вы можете использовать exc_info
аргумент лесорубов по умолчанию:
logging.debug('exception occurred', exc_info=1)
logging.info('exception occurred', exc_info=1)
logging.warning('exception occurred', exc_info=1)
Доступ к сообщению об исключении
Имейте в виду, что библиотеки могут выдавать исключения с сообщениями как любые из байтовых строк в кодировке Unicode или (utf-8, если вам повезет). Если вам действительно нужно , чтобы получить доступ текста в виде исключения, единственный надежный способ, который будет работать всегда, заключается в использовании repr(e)
или %r
форматирования строк:
>>> try:
... raise Exception(u'föö')
... except Exception as e:
... logging.exception('received this exception: %r' % e)
...
ERROR:root:received this exception: Exception(u'f\xf6\xf6',)
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
Exception: f\xf6\xf6