Python Language
Protokollierung
Suche…
Einführung in die Python-Protokollierung
Dieses Modul definiert Funktionen und Klassen, die ein flexibles Ereignisprotokollierungssystem für Anwendungen und Bibliotheken implementieren.
Der Hauptvorteil der Protokollierungs-API, die von einem Standardbibliotheksmodul bereitgestellt wird, besteht darin, dass alle Python-Module an der Protokollierung teilnehmen können, sodass Ihr Anwendungsprotokoll Ihre eigenen Nachrichten enthalten kann, die in Nachrichten von Drittanbieter-Modulen integriert sind.
So lass uns anfangen:
Beispielkonfiguration direkt im Code
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')
Ausgabebeispiel:
2016-07-26 18:53:55,332 root DEBUG this is a debug test
Beispielkonfiguration über eine INI-Datei
Angenommen, die Datei heißt logging_config.ini. Weitere Informationen zum Dateiformat finden Sie im Logging-Konfigurationsabschnitt des Logging-Lernprogramms .
[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
Verwenden logging.config.fileConfig()
dann logging.config.fileConfig()
im Code:
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')
Beispielkonfiguration über ein Wörterbuch
Ab Python 2.7 können Sie ein Wörterbuch mit Konfigurationsdetails verwenden. PEP 391 enthält eine Liste der obligatorischen und optionalen Elemente im Konfigurationswörterbuch.
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')
Ausnahmen für die Protokollierung
Wenn Sie Ausnahmen protokollieren möchten, können und sollten Sie die Methode logging.exception(msg)
verwenden:
>>> 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
Übergeben Sie die Ausnahme nicht als Argument:
Da logging.exception(msg)
ein msg
logging.exception(msg)
erwartet, ist es eine häufige Gefahr, die Ausnahme wie folgt an den Protokollierungsaufruf zu übergeben:
>>> 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
Es sieht zwar so aus, als wäre dies anfangs das Richtige, aber es ist problematisch, weil Ausnahmen und verschiedene Codierungen im Protokollierungsmodul zusammenarbeiten:
>>> 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
Beim Versuch, eine Ausnahme zu protokollieren, die Unicode-Zeichen enthält, schlägt dieser Weg fehl . logging.exception(e)
wird der Stacktrace der ursprünglichen Ausnahme logging.exception(e)
indem sie durch eine neue überschrieben wird, die während der Formatierung des logging.exception(e)
von logging.exception(e)
.
Natürlich kennen Sie in Ihrem eigenen Code die Kodierung in Ausnahmen. Drittanbieter-Bibliotheken können dies jedoch auf andere Weise behandeln.
Richtige Benutzung:
Wenn Sie statt der Ausnahme einfach eine Nachricht übergeben und Python seine Magie anwenden lassen, funktioniert es:
>>> 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
Wie Sie sehen, verwenden wir in diesem Fall nicht e
, und der Aufruf von logging.exception(...)
formatiert die jüngste Ausnahme magisch.
Protokollierung von Ausnahmen mit Nicht-FEHLER-Protokollierungsstufen
Wenn Sie eine Ausnahme mit einer anderen Protokollebene als ERROR protokollieren möchten, können Sie das Argument exc_info
der Standardprotokollierer verwenden:
logging.debug('exception occurred', exc_info=1)
logging.info('exception occurred', exc_info=1)
logging.warning('exception occurred', exc_info=1)
Zugriff auf die Nachricht der Ausnahme
Beachten Sie, dass Bibliotheken da draußen Ausnahmen mit Meldungen als Unicode oder (utf-8, wenn Sie Glück haben) Byte-Zeichenfolgen auslösen können. Wenn Sie wirklich auf den Text einer Ausnahme zugreifen müssen, ist die einzige zuverlässige Methode, die immer funktioniert, die Verwendung von repr(e)
oder der Zeichenfolge %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