Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strangeness with a decorator

I want to make a decorator which will catch exceptions and adequately logged their.

def logger(foo):
    try:
        print foo()
    except Exception as e:
        print e

@logger
def d():
    return 2/2

if __name__ == '__main__':
    d()

Thats right i think, but then I run it and I have an exception like this:

1

Traceback (most recent call last):

  File "log.py", line 14, in <module>

    d()

TypeError: 'NoneType' object is not callable

Why interpreter tells me that the function has None type, but call it and print answer?

like image 381
Denis Avatar asked Jan 13 '12 18:01

Denis


2 Answers

Your decorator needs to return a function, but it's not returning anything, hence the 'TypeError: 'NoneType' object is not callable'. You can implement it this way:

def logger(foo):
    def fn():
        try:
            print foo()
        except Exception as e:
            print e
    return fn

Check out This question for a good example of how to write/use a decorator.

like image 136
jeffknupp Avatar answered Nov 18 '22 02:11

jeffknupp


logger as you have defined, does not return a value. All such functions can be thought of as returning None. You have not defined your decorator correctly. It should look more like this:

def logger(foo):
    def _logger(foo):
        try:
            print foo()
         except Exception as e:
            print e
    return _logger

...but keep in mind that this loses a great deal of information, catches and swallows a great deal of exceptions, and also swallows any return values from the foo function so decorated. While you probably do something different in your production code than what you have shown here, the important thing is that the decorator function must itself return a function that can be called (_logger in my example).

like image 2
multipleinterfaces Avatar answered Nov 18 '22 01:11

multipleinterfaces