[Python-Dev] PEP 492 vs. PEP 3152, new round (original) (raw)
Yury Selivanov yselivanov.ml at gmail.com
Fri Apr 24 23:51:30 CEST 2015
- Previous message (by thread): [Python-Dev] PEP 492 vs. PEP 3152, new round
- Next message (by thread): [Python-Dev] PEP 492 vs. PEP 3152, new round
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Lukasz,
On 2015-04-24 5:37 PM, Łukasz Langa wrote:
(Though maybe we should consider
await for
andawait 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 acontainer” and “await with acontextmanager():” also read pretty well. It’s also more consistent with being the one way of finding “yield points”. OTOH, “await with acontextmanager():” 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 requiredait._anext_()
to return a future, which can either raise good oldStopIteration
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.setresult(self.buffer.popleft()) else: fut.setexception(StopIteration) While this is elegant, my concern is that one-future-per-iteration-step might be bad for performance. Maybe consider the following. Theasync 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 COCOROUTINE.
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
- Previous message (by thread): [Python-Dev] PEP 492 vs. PEP 3152, new round
- Next message (by thread): [Python-Dev] PEP 492 vs. PEP 3152, new round
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]