25 Stimmen

Verwendung von functools.wraps mit einem Logging-Dekorator

Ich versuche, einen einfachen Dekorator zu schreiben, der eine bestimmte Anweisung protokolliert, bevor er die dekorierte Funktion aufruft. Die protokollierten Anweisungen sollten beide von der gleichen Funktion zu kommen scheinen, was ich dachte, war der Zweck von functools.wraps().

Warum funktioniert der folgende Code:

import logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(funcName)20s - %(message)s')

from functools import wraps

def log_and_call(statement):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            logging.info(statement)            
            return func(*args, **kwargs)
        return wrapper
    return decorator

@log_and_call("This should be logged by 'decorated_function'")
def decorated_function():
    logging.info('I ran')

decorated_function()

führen zu Protokollerklärungen wie:

             wrapper - This should be logged by 'decorated_function'
  decorated_function - I ran

Ich dachte, der Aufruf von wraps würde wrapper mit dem Namen von decorated_function umbenennen.

Ich verwende Python 2.7.1.

-1voto

abeyer Punkte 735

Ich vermute, dass das Logging-Modul das __name__-Attribut für ein Funktionsobjekt verwendet. Das ändert sich in der Regel nicht, auch wenn Sie die Funktion auf einen anderen Namen zuweisen ... Sie würden die gleichen Ergebnisse tun etwas wie sehen:

def foo()
  logging.info("in foo")
bar = foo
bar()

Sie erhalten foo - in foo , nicht bar - in foo wenn Sie die Bar aufrufen.

Die Dekorateure machen etwas Ähnliches unter der Haube.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X