[Python-Dev] asyncio: how to interrupt an async def w/ finally: ( e.g. Condition.wait() )

Kevin Conway kevinjacobconway at gmail.com
Sat Dec 19 19:26:03 EST 2015


> An async procedure call whose refcount reaches zero without completing
simply goes away; finally: blocks are *not* called and there is *no*
warning.

I believe OP is looking at these two scenarios:

def generator():
    try:
        yield None
        yield None
    finally:
        print('finally')


gen = generator()
gen.send(None)
del gen
# prints finally on GC


class Awaitable:
    def __await__(self):
        return self
    def __next__(self):
        return self


async def coroutine():
    try:
        await Awaitable()
        await Awaitable()
    finally:
        print('finally')


coro = coroutine()
coro.send(None)
del coro
# prints finally on GC

I don't see any difference in the behaviour between the two. My guess is
that OP's code is not hitting a zero refcount.

On Sat, Dec 19, 2015 at 5:00 PM Gustavo Carneiro <gjcarneiro at gmail.com>
wrote:

> I tried to reproduce the problem you describe, but failed.  Here's my test
> program (forgive the awful tab indentation, long story):
>
> --------------
> import asyncio
>
> async def foo():
> print("resource acquire")
> try:
> await asyncio.sleep(100)
> finally:
> print("resource release")
>
>
> async def main():
> task = asyncio.ensure_future(foo())
> print("task created")
> await asyncio.sleep(0)
> print("about to cancel task")
> task.cancel()
> print("task cancelled, about to wait for it")
> try:
> await task
> except asyncio.CancelledError:
> pass
> print("waited for cancelled task")
>
>
> if __name__ == '__main__':
> loop = asyncio.get_event_loop()
> loop.run_until_complete(main())
> loop.close()
> -----------
>
> I get this output:
>
> ----------------
> 10:54:28 ~/Documents$ python3.5 foo.py
> task created
> resource acquire
> about to cancel task
> task cancelled, about to wait for it
> resource release
> waited for cancelled task
> ----------------
>
> Which seems to indicate that the finally clause is correctly executed when
> the task is waited for, after being cancelled.
>
> But maybe I completely misunderstood your problem...
>
>
> On 19 December 2015 at 21:40, Matthias Urlichs <matthias at urlichs.de>
> wrote:
>
>> On 19.12.2015 20:25, Guido van Rossum wrote:
>> > Perhaps you can add a check for a simple boolean 'stop' flag to your
>> > condition check, and when you want to stop the loop you set that flag
>> > and then call notify() on the condition. Then you can follow the
>> > standard condition variable protocol instead of all this nonsense. :-)
>> Your example does not work.
>>
>> >    def stop_it(self):
>> >        self.stopped = True
>> >        self.uptodate.notify()
>>
>> self.uptodate needs to be locked before I can call .notify() on it.
>> Creating a new task just for that seems like overkill, and I'd have to
>> add a generation counter to prevent a race condition. Doable, but ugly.
>>
>> However, this doesn't fix the generic problem; Condition.wait() was just
>> what bit me today.
>> When a non-async generator goes out of scope, its finally: blocks will
>> execute. An async procedure call whose refcount reaches zero without
>> completing simply goes away; finally: blocks are *not* called and there
>> is *no* warning.
>> I consider that to be a bug.
>>
>> --
>> -- Matthias Urlichs
>>
>> _______________________________________________
>> Python-Dev mailing list
>> Python-Dev at python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>>
> Unsubscribe:
>> https://mail.python.org/mailman/options/python-dev/gjcarneiro%40gmail.com
>>
>
>
>
> --
> Gustavo J. A. M. Carneiro
> Gambit Research
> "The universe is always one step beyond logic." -- Frank Herbert
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/kevinjacobconway%40gmail.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20151220/519bb949/attachment-0001.html>


More information about the Python-Dev mailing list