Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do __enter__ and __exit__ work in Python decorator classes?

I'm trying to create a decorator class that counts how many times a function is called, but I'm getting an error message that says:

    "TypeError: __exit__() takes exactly 1 argument (4 given)" 

and I really don't know how I'm giving it four arguments. My code looks like this:

class fcount2(object):     __instances = {}     def __init__(self, f):         self.__f = f         self.__numcalls = 0         fcount2.__instances[f] = self      def __call__(self, *args, **kwargs):         self.__numcalls += 1         return self.__f(*args, **kwargs)      def __enter__(self):         return self      def __exit__(self):         return self      @staticmethod     def count(f):         return fcount2.__instances[self.__f].__numcalls   @fcount2 def f(n):     return n+2  for n in range(5):     print f(n)    print 'f count =',f.count  def foo(n):     return n*n  with fcount2(foo) as g:     print g(1)     print g(2) print 'g count =',g.count print 'f count =',f.count  with fcount2(f) as g:     print g(1)     print g(2) print 'g count =',g.count print 'f count =',f.count  with f:     print f(1)     print g(2) print 'g count =',g.count print 'f count =',f.count 

Are there some other parameters I should (or shouldn't) be passing into the def exit function? Any tips or ideas would be appreciated.

As an aside, my line of code that says "print 'f count =',f.count" appears to be outputting the memory address rather than the value, but that's a whole different problem.

like image 452
user3402743 Avatar asked Mar 14 '14 23:03

user3402743


People also ask

What does __ exit __ do in Python?

__exit__ in Python Context manager is used for managing resources used by the program. After completion of usage, we have to release memory and terminate connections between files.

What does __ enter __ do in Python?

__enter__ and [__exit__] both are methods that are invoked on entry to and exit from the body of "the with statement" (PEP 343) and implementation of both is called context manager. the with statement is intend to hiding flow control of try finally clause and make the code inscrutable.

How do you exit a class in Python?

Python exit commands: quit(), exit(), sys. exit() and os. _exit() The functions quit() , exit() , sys.

What should __ exit __ return?

__exit__() documentation: If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.


1 Answers

the __exit__() method should accept information about exceptions that come up in the with: block. See here.

The following modification of your code works:

def __exit__(self, exc_type, exc_value, tb):     if exc_type is not None:         traceback.print_exception(exc_type, exc_value, tb)         # return False # uncomment to pass exception through      return True 

Then you can try raising an exception in one of your with: blocks and it'll be caught in __exit__().

like image 71
Noah Avatar answered Oct 04 '22 00:10

Noah