When an asynchronous generator is about to be garbage collected,
it calls its cached finalizer. The assumption is that the finalizer
will schedule an ``aclose()`` call with the loop that was active
when the iteration started.
For instance, here is how asyncio can be modified to allow
safe finalization of asynchronous generators::
# asyncio/base_events.py
class BaseEventLoop:
def run_forever(self):
...
old_finalizer = sys.get_asyncgen_finalizer()
sys.set_asyncgen_finalizer(self._finalize_asyncgen)
try:
...
finally:
sys.set_asyncgen_finalizer(old_finalizer)
...
def _finalize_asyncgen(self, gen):
self.create_task(gen.aclose())
``sys.set_asyncgen_finalizer`` is thread-specific, so several event
loops running in parallel threads can use it safely.
When asynchronous generator is about to be garbage collected event loop
starts task to execute aclose, right? Can't such situation happen when
this task is not finished at the moment event loop is closed? Something
like:
async def gen():
try:
yield 1
yield 2
yield 3
except GeneratorExit as exc:
await asyncio.sleep(100)
raise exc
async def main():
async for i in gen():
if i == 1:
break
# main() and event loop is about to finish here,
# while task to aclose will last much longer.
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
_______________________________________________
Async-sig mailing list
Async-sig@python.org
https://mail.python.org/mailman/listinfo/async-sig
Code of Conduct: https://www.python.org/psf/codeofconduct/