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

Matthias Urlichs matthias at urlichs.de
Sat Dec 19 10:43:55 EST 2015


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()
```


More information about the Python-Dev mailing list