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

Gustavo Carneiro gjcarneiro at gmail.com
Sat Dec 19 17:59:10 EST 2015


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20151219/2cfeff36/attachment-0001.html>


More information about the Python-Dev mailing list