You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fromanyioimportCancelScopeimportasynciofromcontextlibimportasynccontextmanager@asynccontextmanagerasyncdefcm():
withCancelScope() asscope:
scope.cancel() # Remove this and everything works.awaitasyncio.sleep(1)
yieldscopeasyncdefmain():
asyncwithcm() asscope:
passasyncio.run(main())
Run it causes this exception.
Traceback (most recent call last):
File "/tmp/anyiobug.py", line 17, in <module>
asyncio.run(main())
File "/home/jonathan/.pyenv/versions/3.9.13/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/home/jonathan/.pyenv/versions/3.9.13/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
return future.result()
File "/tmp/anyiobug.py", line 14, in main
async with cm() as scope:
File "/home/jonathan/.pyenv/versions/3.9.13/lib/python3.9/contextlib.py", line 183, in __aenter__
raise RuntimeError("generator didn't yield") from None
RuntimeError: generator didn't yield
I'm wondering whether there is something fundamentally wrong with this snippet. My understanding is that a cancel scope can be cancelled at any point in time. But asynccontextmanager either expects a yield or an Exception, it doesn't get neither of them.
How would it be possible to prevent this situation? We have something similar happen in a much more complex codebase, and I'm afraid that any usage of task groups or cancel scopes within an asynccontextmanager is prone to this bug.
Here is a related issue about suppressing CancelledError: #374
The text was updated successfully, but these errors were encountered:
The asynccontextmanager needs the function it wraps to yield exactly once (unless it raises an exception), period, end of discussion. Your code is not yielding and it doesn't raise an exception either, so …
My workaround for this problem was along these lines:
@asynccontextmanager
async def crashy():
yielded = False
try:
… something
yielded = True
yield whatever
… something more
finally:
if not yielded:
yield None # or raise a RuntimeError or whatever
Take this piece of code:
Run it causes this exception.
I'm wondering whether there is something fundamentally wrong with this snippet. My understanding is that a cancel scope can be cancelled at any point in time. But
asynccontextmanager
either expects ayield
or anException
, it doesn't get neither of them.How would it be possible to prevent this situation? We have something similar happen in a much more complex codebase, and I'm afraid that any usage of task groups or cancel scopes within an
asynccontextmanager
is prone to this bug.Here is a related issue about suppressing
CancelledError
: #374The text was updated successfully, but these errors were encountered: