Frage

Kann ich die Parameter der zuletzt aufgerufenen Funktion im Traceback abrufen?Wie?

Ich möchte einen Fänger für Standardfehler erstellen, um lesbaren Code zu erstellen und dem Benutzer dennoch detaillierte Informationen bereitzustellen.

Im folgenden Beispiel möchte ich, dass GET_PARAMS mir ein Tupel von Parametern zurückgibt, die an os.chown bereitgestellt werden.Untersuchen der inspect Das von Alex Martelli empfohlene Modul konnte ich nicht finden.

def catch_errors(fn):
    def decorator(*args, **kwargs):
        try:
            return fn(*args, **kwargs)
        except (IOError, OSError):
            msg = sys.exc_info()[2].tb_frame.f_locals['error_message']
            quit(msg.format(SEQUENCE_OF_PARAMETERS_OF_THE_LAST_FUNCTION_CALLED)\
            + '\nError #{0[0]}: {0[1]}'.format(sys.exc_info()[1].args), 1)
    return decorator

@catch_errors
def do_your_job():
    error_message = 'Can\'t change folder ownership \'{0}\' (uid:{1}, gid:{2})'
    os.chown('/root', 1000, 1000) # note that params aren't named vars.

if __name == '__main__' and os.getenv('USERNAME') != 'root':
    do_your_job()

(Dank an Jim Robert für den Dekorateur)

War es hilfreich?

Lösung

Das Problem bei der Verwendung eines Dekorateur für das, was Sie erreichen wollen, ist, dass der Rahmen des Exception-Handler erhält do_your_job()s ist, nicht os.listdir()s, os.makedirs()s oder os.chown()s. So Ihre Informationen werden den Druck werden die Argumente do_your_job(). Um das Verhalten Ich glaube, Sie erhalten möchten, würden Sie haben alle Bibliotheksfunktionen dekorieren Sie anrufen.

Andere Tipps

Denken Sie bei solchen Inspektionsaufgaben immer zuerst an das Modul inspect in der Standardbibliothek.Hier, inspect.getargvalues gibt Ihnen die Argumentwerte für einen gegebenen Rahmen und inspect.getinnerframes liefert Ihnen die interessierenden Frames eines Traceback-Objekts.

Hier

ist ein Beispiel für eine solche Funktion und einige Probleme, die man nicht umgehen kann:

import sys

def get_params(tb):
    while tb.tb_next:
        tb = tb.tb_next
    frame = tb.tb_frame
    code = frame.f_code
    argcount = code.co_argcount
    if code.co_flags & 4: # *args
        argcount += 1
    if code.co_flags & 8: # **kwargs
        argcount += 1
    names = code.co_varnames[:argcount]
    params = {}
    for name in names:
        params[name] = frame.f_locals.get(name, '<deleted>')
    return params


def f(a, b=2, c=3, *d, **e):
    del c
    c = 4
    e['g'] = 6
    assert False

try:
    f(1, f=5)
except:
    print get_params(sys.exc_info()[2])

Die Ausgabe lautet:

{'a': 1, 'c': 4, 'b': 2, 'e': {'g': 6, 'f': 5}, 'd': ()}

habe ich nicht verwendet inspect.getinnerframes() eine andere Art und Weise zu zeigen, benötigt Rahmen zu erhalten. Obwohl es ein wenig vereinfacht, sondern auch einige zusätzliche Arbeit tun, die nicht für Sie benötigt wird, während relativ langsam ist (inspect.getinnerframes() liest Quelldatei für jedes Modul in Traceback, das für einen Debug-Aufruf ist nicht wichtig, aber könnte ein Problem in anderen Fällen sein ).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top