Trace-Decorator

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
ocoal
User
Beiträge: 32
Registriert: Mittwoch 20. Juli 2011, 22:44

Hallo zusammen,

ich verwende in meinen Projekten gerne zu Debug-Zwecken die Information im Log *wann* eine Funktion beginnt (aufgerufen wurde), und *wann* sie wieder verlassen wurde.

Hierfür habe ich folgenden Decorator entwickelt:

Code: Alles auswählen

import logging # dies ist nur eine beispielhafte Konfiguration des Python-Loggings

logging.basicConfig(format='%(message)s')
_log = logger = logging.getLogger('')
_log.setLevel(logging.DEBUG)

TRACE_INDENT = 2
_trace_indent = 0
def trace(f):
    def decorator(*args, **kwargs):
        global _trace_indent
        name = f.__name__
        if len(args) > 0 and hasattr(args[0].__class__, f.__name__):
            # means: first passed argument is 'self'
            name = "%s.%s" % (args[0].__class__.__name__, name)
        _log.debug('%s<trace func="%s">' % (_trace_indent * ' ', name))
        result = None
        try:
            _trace_indent += TRACE_INDENT
            result = f(*args, **kwargs)
        finally:
            _trace_indent = [0, _trace_indent - TRACE_INDENT][_trace_indent > 0]
            _log.debug('%s</trace>' % (_trace_indent * ' '))
        return result
    return decorator
Sieht dann im Code angewendet so z.B. aus:

Code: Alles auswählen

from ... import trace # z.B. aus einem Util-Modul

@trace
def foo():
    print("foo")

class Test(object):
    def __init__(self):
        pass
    
    @trace
    def bar(self):
        print("bar")
        self.mar()

    @trace
    def mar(self):
        print("mar")

foo()
Test().bar()
Mit folgenden Output:

Code: Alles auswählen

<trace func="foo">
foo
</trace>
<trace func="Test.bar">
bar
  <trace func="Test.mar">
mar
  </trace>
</trace>
Wie man gut erkennen kann, werden die Trace-Informationen in XML-Tags bei geschachtelten Methodenaufrufen eingerückt. Die Anzahl der Einrückungs-Tiefe (Leerzeichen) ist über TRACE_INDENT variabel und je nach Geschmack konfigurierbar.

-Colin-
Antworten