Monday, February 7, 2011

Logging Python method calls using method decorators

Python decorator is not necessarily the easiest concept to understand. This post provides a complete sample of using Python method decorator to control how method calls are logged. I hope you can use this sample as a reference while trying to understand the decorator concept. In the code I defined a class “C” that has three methods, “Func1”, “Func2”, and “Func3”. Each function is decorated by one of the two decorators, “tracing” and “logging”, defined in the code. “tracing” decorator logs method calls before and after a method is invoked; and “logging” decorator controls logging behaviors by returning different callables based on the Level parameter.


def tracing(F):
    def wrapper(*args):
        print("\nBefore calling '{0}'".format(F.__name__))
        F(*args)
        print("After calling '{0}'\n".format(F.__name__))
    return wrapper

def logging(Level):
    def actualDecorator(F):
        if Level =="Verbose":
            return tracing(F)
        else:
            return F
    return actualDecorator

Log_Level = "Verbose"

class C:
    @logging(Log_Level)
    def Func1(self):
        print("Calling Func1")
    @logging("None")
    def Func2(self):
        print("Calling Func2")
    @tracing
    def Func3(self):
        print("Calling Func3")

c = C()
c.Func1()   #Func1 is logged when global Log_Level is set to “Verbose”
c.Func2()   #Func2 overrides global flag with “None”
c.Func3()   #Func3 is logged always as it skips log level checks


Above code outputs this when executed:


>>>

Before calling 'Func1'
Calling Func1
After calling 'Func1'

Calling Func2

Before calling 'Func3'
Calling Func3
After calling 'Func3'

>>>


Two key points to take away:

  1. In Python, a decorator is a callable that returns a callable.
  2. A parameterized decorator is a callable that returns a decorator (so it’s a callable that returns a callable that returns a callable).

0 comments:

Post a Comment