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

Guido van Rossum guido at python.org
Sat Dec 19 14:25:16 EST 2015


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. :-)

class Foo:
    async def some_method(self):
        self.uptodate = asyncio.Condition()
        self.stopped = False
        …
        await self.uptodate.acquire()
        try:
            while (not self.stopped) and self.some_condition():
                await self.uptodate.wait()
        finally:
            self.uptodate.release()
    def stop_it(self):
        self.stopped = True
        self.uptodate.notify()

On Sat, Dec 19, 2015 at 7:43 AM, Matthias Urlichs <matthias at urlichs.de>
wrote:

> The following code has a problem: the generator returned by .wait() has a
> finally: section. When self.stopped is set, it still needs to run. As it is
> asynchronous (it needs to re-acquire the lock), I need to come up with a
> reliable way to wait for it. If I don't, .release() will throw an exception
> because the lock is still unlocked.
>
> The best method to do this that I've come up with is the five marked lines.
> I keep thinking there must be a better way to do this (taking into account
> that I have no idea whether the 'await r' part of this is even necessary).
>
>
> ```
> class StopMe(BaseException):
>     pass
> class Foo:
>     async dev some_method(self):
>         self.uptodate = asyncio.Condition()
>         self.stopped = asyncio.Future()
>>         await self.uptodate.acquire()
>         try:
>             while self.some_condition():
>                 w = self.uptodate.wait()
>                 await asyncio.wait([w,self.stopped], loop=self.conn._loop,
> return_when=asyncio.FIRST_COMPLETED)
>                 with contextlib.suppress(StopMe):  # FIXME?
>                     r = w.throw(StopMe())          # FIXME?
>                     if r is not None:              # FIXME?
>                         await r                    # FIXME?
>                 await w                            # FIXME?
>         finally:
>             self.uptodate.release()
> ```
> _______________________________________________
> 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/guido%40python.org
>



-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20151219/5b2d492b/attachment-0001.html>


More information about the Python-Dev mailing list