With class as contextmanager

Ian Kelly ian.g.kelly at gmail.com
Tue Jan 24 17:31:31 EST 2017


On Tue, Jan 24, 2017 at 2:31 PM, This Wiederkehr
<this.wiederkehr at gmail.com> wrote:
> Hellou
>
> having a class definition:
>
> class Test():
>
> @classmethod
> def __enter__(cls):
>     pass
>
> @classmethod
> def __exit__(cls, exception_type, execption_value, callback):
>     pass
>
> now using this as a contextmanager does not work, even though Test is an
> object and has the two required methods __enter__ and __exit__.
>
> it fails with:
> #Attribute Error: __enter__
>
>
> This is not working because behind the scene it does something like:
> type(Test).__enter__(Test)
>
> But isn't this supposed to be working?
>
> I am asking because I'd like to implement the clean up behaviour for
> multiple instances directly into the class:
>
> with Test:
>     testinstance1 = Test()
>     testinstance2 = Test()
> # on context exit Test.__exit__ should take care on cleaning up
> testinstance1 and testinstance2.

Special dunder methods are generally only looked up on the object's
class, not on the object itself. If you wish to use a class object as a
context manager then you need to define __enter__ and __exit__ on the
class's class, i.e. its metaclass.

Alternatively you could separate the context manager from the testing
class and make Test be just an object that defines __enter__, __exit__
and __call__, with __call__ creating and returning a new instance of
the actual testing class.


More information about the Python-list mailing list