Szukaj…


Wprowadzenie do rejestrowania w języku Python

Ten moduł definiuje funkcje i klasy, które implementują elastyczny system rejestrowania zdarzeń dla aplikacji i bibliotek.

Kluczową zaletą interfejsu API rejestrowania udostępnianego przez standardowy moduł biblioteczny jest to, że wszystkie moduły Pythona mogą uczestniczyć w logowaniu, dzięki czemu dziennik aplikacji może zawierać własne wiadomości zintegrowane z komunikatami z modułów innych firm.

A więc zacznijmy:

Przykładowa konfiguracja bezpośrednio w kodzie

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

Przykład wyjściowy:

2016-07-26 18:53:55,332 root         DEBUG    this is a debug test

Przykładowa konfiguracja za pomocą pliku INI

Zakładając, że plik nazywa się logowanie_konfiguracyjny.ini. Więcej informacji na temat formatu pliku znajduje się w sekcji konfiguracji rejestrowania w samouczku rejestrowania .

[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

Następnie użyj logging.config.fileConfig() w kodzie:

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

Przykładowa konfiguracja za pomocą słownika

Począwszy od wersji Python 2.7 można używać słownika ze szczegółami konfiguracji. PEP 391 zawiera listę elementów obowiązkowych i opcjonalnych w słowniku konfiguracji.

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

Rejestrowanie wyjątków

Jeśli chcesz rejestrować wyjątki, możesz i powinieneś skorzystać z metody dziennika.exception 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

Nie przekazuj wyjątku jako argumentu:

Ponieważ logging.exception(msg) oczekuje argumentu msg , częstym błędem jest przekazywanie wyjątku do wywołania rejestrowania w następujący sposób:

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

Choć może się wydawać, że jest to właściwe na początku, w rzeczywistości jest problematyczne, ponieważ wyjątki i różne kodowanie współpracują ze sobą w module rejestrowania:

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

Próba zarejestrowania wyjątku zawierającego znaki Unicode w ten sposób zakończy się niepowodzeniem . Ukryje ślad stosu oryginalnego wyjątku, zastępując go nowym, który jest wywoływany podczas formatowania wywołania logging.exception(e) .

Oczywiście we własnym kodzie możesz być świadomy kodowania w wyjątkach. Jednak biblioteki innych firm mogą obsługiwać to w inny sposób.

Prawidłowa obsługa:

Jeśli zamiast wyjątku po prostu przekażesz wiadomość i pozwolisz Pythonowi wykonać swoją magię, zadziała:

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

Jak widać, w tym przypadku tak naprawdę nie używamy e , wywołanie logging.exception(...) magicznie formatuje najnowszy wyjątek.

Rejestrowanie wyjątków z poziomami dziennika innymi niż BŁĄD

Jeśli chcesz zarejestrować wyjątek na innym poziomie dziennika niż BŁĄD, możesz użyć argumentu exc_info domyślnych programów rejestrujących:

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

Dostęp do komunikatu wyjątku

Pamiętaj, że biblioteki mogą generować wyjątki od komunikatów takich jak Unicode lub (utf-8, jeśli masz szczęście) ciągi bajtów. Jeśli naprawdę potrzebujesz dostępu do tekstu wyjątku, jedynym niezawodnym sposobem, który zawsze będzie działał, jest użycie repr(e) lub formatowanie ciągu %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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow