How the heck does async/await work in Python 3.5

Ian Kelly ian.g.kelly at gmail.com
Sat Feb 20 03:14:48 EST 2016


On Sat, Feb 20, 2016 at 12:57 AM, Chris Angelico <rosuav at gmail.com> wrote:
> On Sat, Feb 20, 2016 at 6:48 PM, Ian Kelly <ian.g.kelly at gmail.com> wrote:
>> As another point that happens to be fresh in my mind, awaiting a
>> Future on which an exception gets set is supposed to propagate the
>> exception. I recently found that this breaks if the exception in
>> question happens to be StopIteration (granted not one that should
>> generally be allowed to propagate anyway, but that's a separate
>> discussion) for the simple reason that raising StopIteration in a
>> generator is equivalent to returning None.
>
> Solved by PEP 479. Use "from __future__ import generator_stop" to save
> yourself the pain.

Nope.

py> from __future__ import generator_stop
py> import asyncio
py> async def test_coro():
...     fut = asyncio.Future()
...     fut.set_exception(StopIteration())
...     print('received %r' % await fut)
...
py> list(test_coro().__await__())
received None
[]

I think because __future__ imports are per-file, and
asyncio.Future.__iter__ is defined in a file outside my control that
doesn't have the __future__ import.

I suppose that when the generator_stop behavior becomes standard then
it will work, but still that will just cause a RuntimeError to
propagate instead of the desired StopIteration.

It's not really that big a deal since there is a code smell to it, but
it's surprising since intuitively StopIteration should have no special
meaning to a PEP 492 coroutine (it's not an iterator, wink wink, nudge
nudge), and the thing being awaited is a Future, which also doesn't
intuitively look like an iterator. Note that if you just call
Future.result(), then the exception propagates as expected; it's just
awaiting it that doesn't work.


More information about the Python-list mailing list