async enumeration - possible?
Chris Angelico
rosuav at gmail.com
Wed Nov 30 03:20:15 EST 2016
On Wed, Nov 30, 2016 at 7:10 PM, Ian Kelly <ian.g.kelly at gmail.com> wrote:
> On Tue, Nov 29, 2016 at 8:22 PM, Chris Angelico <rosuav at gmail.com> wrote:
>> Interestingly, I can't do that in a list comp:
>>
>>>>> [x async for x in aiterable]
>> File "<stdin>", line 1
>> [x async for x in aiterable]
>> ^
>> SyntaxError: invalid syntax
>>
>> Not sure why.
>
> Because you tried to use an async comprehension outside of a coroutine.
>
> py> [x async for x in y]
> File "<stdin>", line 1
> [x async for x in y]
> ^
> SyntaxError: invalid syntax
> py> async def foo():
> ... [x async for x in y]
> ...
>
> The same is true for async generator expressions. The documentation is
> clear that this is illegal for the async for statement:
>
> https://docs.python.org/3.6/reference/compound_stmts.html#the-async-for-statement
Hmm. The thing is, comprehensions and generators are implemented with
their own nested functions. So I would expect that their use of async
is independent of the function they're in. But maybe we have a bug
here?
>>> async def spam():
... def ham():
... async for i in x:
... pass
...
>>> def ham():
... async for i in x:
File "<stdin>", line 2
async for i in x:
^
SyntaxError: invalid syntax
>>> def ham():
... async def spam():
... async for i in x:
... pass
...
>>>
Clearly the second one is correct to throw SyntaxError, and the third
is correctly acceptable. But the first one, ISTM, should be an error
too.
> Yeah, that's what I would expect. (x async for x in foo) is
> essentially a no-op, just like its synchronous equivalent; it takes an
> asynchronous iterator and produces an equivalent asynchronous
> iterator. Meanwhile, list() can't consume an async iterator because
> the list constructor isn't a coroutine. I don't think it's generally
> possible to "synchronify" an async iterator other than to materialize
> it. E.g.:
>
> def alist(aiterable):
> result = []
> async for value in aiterable:
> result.append(value)
> return result
>
> And I find it a little disturbing that I actually can't see a better
> way to build a list from an async iterator than that.
Oh. Oops. That materialization was exactly what I intended to happen
with the comprehension. Problem: Your version doesn't work either,
although I think it probably _does_ work if you declare that as "async
def alist".
Shows you just how well I understand Python's asyncness, doesn't it?
ChrisA
More information about the Python-list
mailing list