GOOGLE ADS

Dienstag, 12. April 2022

Python-Protokollierung: Stack-Trace deaktivieren

Gibt es eine einfache Möglichkeit, die Protokollierung eines Ausnahme-Stack-Trace in Python 3 zu deaktivieren, entweder in a Handleroder Formatter?

Ich brauche den Stack-Trace in einem anderen Handler, also ist das Setzen exc_info=Falsevon, im Aufruf von Loggernicht möglich. Gibt es einen einfacheren Weg, als nur meinen eigenen zu definieren Formatter?


Lösung des Problems

Die einfachste Option zum Deaktivieren der Traceback-Ausgabe pro Handler besteht darin, eine benutzerdefinierte logging.FilterUnterklasse hinzuzufügen, die das Datensatzobjekt ändert (anstatt Datensätze herauszufiltern).

Der Filter muss einfach exc_infoauf Datensätze gesetzt werden auf None:

class TracebackInfoFilter(logging.Filter):
"""Clear or restore the exception on log records"""
def __init__(self, clear=True):
self.clear = clear
def filter(self, record):
if self.clear:
record._exc_info_hidden, record.exc_info = record.exc_info, None
# clear the exception traceback text cache, if created.
record.exc_text = None
elif hasattr(record, "_exc_info_hidden"):
record.exc_info = record._exc_info_hidden
del record._exc_info_hidden
return True

und fügen Sie diesen Filter zu Ihrem Handler hinzu:

# do not display tracebacks in messages handled with this handler,
# by setting the traceback cache to a non-empty string:
handler_with_no_tracebacks.addFilter(TracebackInfoFilter())

Handler kopieren jedoch keine Protokolldatensätze, und alle anderen Handler, denen später derselbe Protokolldatensatz übergeben wird, ignorieren ebenfalls die Formatierung des Tracebacks. Sie müssen also auch alle anderen Handler konfigurieren, um die Informationen erneut wiederherzustellen:

for handler in logger.handlers:
if not any(isinstance(f, TracebackInfoFilter) for f in handler.filters):
handler.addFilter(TracebackInfoFilter(clear=False))

Wenn jemand alle Traceback-Ausgaben überall deaktivieren möchte, dann wird es vielleicht mühsam, allen Handlern oder Loggern einen benutzerdefinierten Filter hinzuzufügen. In diesem Fall besteht eine weitere Möglichkeit darin, eine benutzerdefinierte Record Factory mit der logging.setLogRecordFactory()Funktion zu registrieren; Setzen Sie einfach das exc_infoAttribut für Datensätze auf None, bedingungslos:

record_factory = logging.getLogRecordFactory()
def clear_exc_text(*args, **kwargs):
record = record_factory(*args, **kwargs)
record.exc_info = None
return record
logging.setLogRecordFactory(clear_exc_text)

Beachten Sie, dass die Standardfabrik nur die logging.LogRecordKlasse ist, aber die obige Funktion tut ihr Bestes, um mit jeder bereits festgelegten benutzerdefinierten Fabrik zu arbeiten.

Natürlich können Sie auch Ihre eigene HandlerUnterklasse erstellen, in der Handler.handle()das Attribut gesetzt und gelöscht exc_infowird:

class NoTracebackHandler(logging.Handler):
def handle(self, record):
info, cache = record.exc_info, record.exc_text
record.exc_info, record.exc_text = None, None
try:
super().handle(record)
finally:
record.exc_info = info
record.exc_text = cache

Keine Kommentare:

Kommentar veröffentlichen

Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...