Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
bpo-44176: Allow asyncio.as_completed()'s first parameter to be a generator yielding awaitables#26228
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
alexdelorenzo commented May 19, 2021 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
the-knights-who-say-ni commented May 19, 2021
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept this contribution by verifying everyone involved has signed the PSF contributor agreement (CLA). Recognized GitHub usernameWe couldn't find a bugs.python.org (b.p.o) account corresponding to the following GitHub usernames: This might be simply due to a missing "GitHub Name" entry in one's b.p.o account settings. This is necessary for legal reasons before we can look at this contribution. Please follow the steps outlined in the CPython devguide to rectify this issue. You can check yourself to see if the CLA has been received. Thanks again for the contribution, we look forward to reviewing it! |
asyncio.as_completed() first parameter to be a generator yielding awaitablesasyncio.as_completed() first parameter to be a generator yielding awaitablesasyncio.as_completed()'s first parameter to be a generator yielding awaitablesThis PR is stale because it has been open for 30 days with no activity. |
uriyyo left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Could you please also add tests to cover case when you pass generator to asyncio.as_completed and asyncio.wait function call?
uriyyo commented Sep 1, 2021 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
After investigation I think that actual problem is in From
But actually this function returns true for generators that is not coroutines: fromasyncioimportiscoroutine, runfromtypesimportcoroutine@coroutinedefcoro(): yielddefnot_coro(): yieldprint(iscoroutine(coro())) # Trueprint(iscoroutine(not_coro())) # TrueBut if we will try to await asyncdefmain(): awaitcoro() # okawaitnot_coro() # will fail with TypeError: object generator can't be used in 'await' expressionIn my opinion Lines 351 to 352 in 863154c
@Fidget-Spinner What is your opinion regarding this problem? Should we ping Yury and Andrew regarding this? UPD: While I was playing with defnot_coro(): yieldasyncdefmain(): awaitgather(not_coro()) # will not failawaitnot_coro() # will failIt looks like a bug, but I should do more investigation. |
Fidget-Spinner commented Sep 1, 2021 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@uriyyo great investigation! That's a really interesting find. IMO, changing the behavior of I think we can ping Yury and Andrew politely on the bug tracker once OP adds tests like you mentioned. BTW, I use asyncio, but you probably have more knowledge about asyncio internals than me :). So this is a learning experience for me too (ie I might make mistakes). |
uriyyo commented Sep 1, 2021
@Fidget-Spinner Ideal solution will be to change behavior of For instance currently, code bellow will not fail: awaitgather(Nonefor_inrange(10))When we have generator: defnot_coro(): yieldIt's not valid to await it: awaitnot_coro() # TypeError: object generator can't be used in 'await' expressionBut all cases below will not fail: awaitcreate_task(not_coro()) awaitensure_future(not_coro()) awaitgather(not_coro()) awaitwait([not_coro()]) awaitwait([not_coro()]) awaitwait_for(not_coro(), 10) awaitshield(not_coro()) forfinas_completed([not_coro()]): print(awaitf)We can fix it be changing _COROUTINE_TYPES= (types.CoroutineType, collections.abc.Coroutine) _iscoroutine_typecache=set() defiscoroutine(obj): """Return True if obj is a coroutine object."""iftype(obj) in_iscoroutine_typecache: returnTrueifisinstance(obj, _COROUTINE_TYPES): # Just in case we don't want to cache more than 100# positive types. That shouldn't ever happen, unless# someone stressing the system on purpose.iflen(_iscoroutine_typecache) <100: _iscoroutine_typecache.add(type(obj)) returnTrueelifisinstance(obj, types.GeneratorType) andobj.gi_code.co_flags&inspect.CO_ITERABLE_COROUTINE: returnTrueelse: returnFalseBut this solution is not backward compatible( |
DevilXD commented Aug 1, 2022 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Just ran into this issue myself and managed to find this PR. Looking forward to it being merged. |
Allow
asyncio.as_completed()'s first parameter to be a generator yielding awaitablesbpo-44176:
asyncio.as_completed()raisesTypeErrorwhen the first supplied parameter is a generator that yields awaitableshttps://bugs.python.org/issue44176