-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Strange behavior with await in a generator expression #76294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
|
PEP-530 is not very clear about >>> async def g(i):
... print(i)
...
>>> async def f():
... result = list(await g(i) for i in range(3))
... print(result)
...
>>> f().send(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
TypeError: 'async_generator' object is not iterableAt the same time a (seemingly) equivalent list comprehension works fine: >>> async def f():
... result = [await g(i) for i in range(3)]
... print(result)
...
>>> f().send(None)
0
1
2
[None, None, None]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIterationI would say that the first case should either behave as a second one, or raise a syntax error. Or is it actually an intended behavior? |
This is equivalent to this code: async def ait():
for i in range(3):
v = await g(i)
yield v
result = list(ait())Where 'ait' is an async generator function. You can't iterate it with the regular 'for x in ...' syntax, and you can't pass it to functions that expect a synchronous iterator (such as 'list'). Similarly, with synchronous code: a = (i for i in range(3))
a[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'generator' object is not subscriptablewhere '(' for ... ')' is another syntax for defining a synchronous generator.
This is equivalent to this code: result = []
for i in range(3):
v = await g(i)
result.append(v)I agree that PEP-530 is a bit vague about this and can be updated. I'll take a look into that. Perhaps we can make the "TypeError: 'async_generator' object is not iterable" error message a bit clearer. Any ideas to improve it are welcome.
No, but we can improve error messages. |
|
A first simple idea that comes to my mind is special-case async generators/iterators in PyObject_GetIter to say something like: TypeError: asynchronous iterable can't be used where an iterable is expected If it is possible to detect that an async generator is resulting from a generator expression, then we can say: TypeError: asynchronous generator expression can't be used as an iterable |
|
The existing error message looks fine to me. I am interested in @gvanrossum's opinion here. |
|
The problem is not the error message -- it is the discrepancy between Ivan is right that when comprehensions were unified with generator expressions in Python 3, the intention was that these two should be equivalent, so it's a bit strange that they are handled differently by PEP 530. A list comprehension without The thing is that PEP 530 doesn't mention generator expressions in the section about how the presence of Given that this is how the PEP defines things, I think it is too late to change, and in the end I agree that we should close the issue. |
Agreed. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: