When does the __exit__ context manager appear, running inside the generator?

I am doing something like a task scheduler, using generators as coroutines. In the code below, I need to do print cleanup deterministically.

In my interaction, it seems that freeing the object from the garbage collector causes exit from the context manager. But I know better than relying on GC time. Is this really a GC calling __exit__ , or is it another mechanism?

How can I strictly force print 'cleanup' ?

 >>> from contextlib import contextmanager >>> @contextmanager ... def foo(): ... print 'setup' ... try: ... yield ... finally: ... print 'cleanup' ... >>> def bar(): ... with foo(): ... while True: ... yield 'bar' ... >>> b = bar() >>> b.next() setup 'bar' >>> b = None cleanup 
+6
source share
2 answers

Yes, the GC calls the __del__ generator cleanup hook, which in turn calls the GeneratorExit function in the generator function to exit the generator (by calling generator.close() ).

This means that the __exit__ context manager hook __exit__ be called whenever the generator function is cleared from memory.

You can manually close the generator yourself, generator.close() :

 b.close() 
+5
source

You have to get the generator to go out. If the nature of the generator should look forever, you can use gen.throw () to throw an exception in the generator.

Actually, I just looked at the specification for generators, and they have a close () method that does just that (it throws a GeneratorExit () exception inside the generator. So just call gen.close () when you are done with any manager the context will refer to its exit methods.The generator will use an exception, so you donโ€™t have to wrap the close () call in the try block:

 >>> b= bar() >>> b.next() setup 'bar' >>> b.close() cleanup >>> 
+2
source

Source: https://habr.com/ru/post/957548/


All Articles