Поиск…


Введение в ведение журнала Python

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

Ключевое преимущество наличия 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 , это общая ошибка, чтобы передать исключение в вызов регистрации, например:

>>> 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

Пытаясь зарегистрировать исключение, содержащее символы unicode, этот путь потерпит неудачу . Он скроет стек из первоначального исключения, переопределив его новым, который logging.exception(e) во время форматирования вашего 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(...) магически форматирует последнее исключение.

Исключения журналов с уровнями журнала не ERROR

Если вы хотите регистрировать исключение с другим уровнем журнала, чем ERROR, вы можете использовать аргумент exc_info для регистраторов по умолчанию:

logging.debug('exception occurred', exc_info=1)
logging.info('exception occurred', exc_info=1)
logging.warning('exception occurred', exc_info=1)

Доступ к сообщению об исключении

Имейте в виду, что библиотеки там могут генерировать исключения с сообщениями как любые юникодные или (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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow