[Async-sig] Asynchronous cleanup is a problem

Yury Selivanov yselivanov at gmail.com
Wed Jul 6 20:25:38 EDT 2016


> On Jul 6, 2016, at 7:06 PM, Nathaniel Smith <njs at pobox.com> wrote:
> 
> On Wed, Jul 6, 2016 at 1:12 PM, Yury Selivanov <yselivanov at gmail.com> wrote:
>> This is an interesting idea, but I wonder if instead of using ‘async with’ we can actually augment ‘async for’ to do the async finalization.
>> 
>> We can add an __aiter_close__ special method which will return an awaitable.  In this case, ‘async for’ can always look for that method and call it at the end of the iteration.  Async generators will implement the method to make sure that ‘finally’ is always executed (any number of awaits in ‘finally’ is OK; ‘yield’ expressions cannot be used).
> 
> I was wondering about that too. This is a fairly substantial change to
> how iterators work, though -- currently, it's totally legal and
> sometimes very useful to do things like
> 
> it = open("...")
> # Discard header line (first non-commented line)
> for line in it:
>    if not line.startswith("#"):
>        break
> for body_line in it:
>
Right.  __aiter_close__ won’t work.

The problem is that the GC can’t execute async code, and we don’t have any control over GC.  What if we add a mechanism to control how async generators (AG) are destructed.  Let’s say we add new function to the sys module - `sys.set_async_generator_finalizer(finalizer)`.  We already have sys.set_coroutine_wrapper(), so this isn’t something unprecedented.

With this new function, when an AG is about to be finalized, the interpreter will resurrect it and call the `finalizer`.  The finalizer function will be installed by an event loop, and will execute ‘await AG.aclose()’ in the context of that loop.

We can issue a ResourceWarning if an AG (not fully exhausted) is GCed and there is no async finalizer.

Yury


More information about the Async-sig mailing list