Lukasz,
On 2015-04-24 5:37 PM, Łukasz Langa wrote:
(Though maybe we should consider `await for` and `await with`? That would have
the advantage of making it easy to scan for all suspension points by searching
for /await/. But being a verb it doesn't read very well.)
I’m on the fence here.
OT1H, I think “await for something in a_container” and “await with
a_context_manager():” also read pretty well. It’s also more consistent with
being the one way of finding “yield points”.
OTOH, “await with a_context_manager():” suggests the entire statement is
awaited on, which is not true. “async with” is more opaque in this way, it
simply states “there are going to be implementation-specific awaits inside”. So
it’s more consistent with “async def foo()”.
This. I also think of 'await with' as I'm awaiting on the whole
statement. And I don't even know how to interpret that.
6. StopAsyncException
I'm not sure about this. The motivation given in the PEP seems to focus on the
need for `__anext__` to be async. But is this really the right pattern? What if
we required `ait.__anext__()` to return a future, which can either raise good
old `StopIteration` or return the next value from the iteration when awaited?
I'm wondering if there are a few alternatives to be explored around the async
iterator protocol still.
So are you suggesting to pass the returned value in a future? In this case the
future would need to be passed to __anext__, so the Cursor example from the PEP
would look like this:
class Cursor:
def __init__(self):
self.buffer = collections.deque()
def _prefetch(self):
...
async def __aiter__(self):
return self
async def __anext__(self, fut):
if not self.buffer:
self.buffer = await self._prefetch()
if self.buffer:
fut.set_result(self.buffer.popleft())
else:
fut.set_exception(StopIteration)
While this is elegant, my concern is that one-future-per-iteration-step might
be bad for performance.
Maybe consider the following. The `async def` syntax decouples the concept of a
coroutine from the implementation. While it’s still based on generators under
the hood, the user no longer considers his “async function” to be a generator
or conforming to the generator protocol. From the user’s perpective, it’s
obvious that the return below means something different than the exception:
async def __anext__(self):
if not self.buffer:
self.buffer = await self._prefetch()
if not self.buffer:
raise StopIteration
return self.buffer.popleft()
So, the same way we added wrapping in RuntimeErrors for generators in PEP 479,
we might add transparent wrapping in a _StopAsyncIteration for CO_COROUTINE.
FWIW I have to experiment more with the reference implementation,
but at the moment I'm big -1 on touching StopIteration for
coroutines. It's used for too many things.
Thanks!
Yury
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com