Open zpz opened 10 months ago
I understand this is related to event_loop shutdown. If I add this
@pytest.fixture(scope='function')
def event_loop(request):
loop = asyncio.get_event_loop_policy().new_event_loop()
try:
yield loop
finally:
try:
asyncio.runners._cancel_all_tasks(loop)
loop.run_until_complete(loop.shutdown_asyncgens())
loop.run_until_complete(loop.shutdown_default_executor())
finally:
loop.close()
The 3 issues I mentioned are all gone, but there's this warning
/usr/local/lib/python3.10/dist-packages/pytest_asyncio/plugin.py:749: DeprecationWarning: The event_loop fixture provided by pytest-asyncio has been redefined in
/home/docker-user/mpservice/tests/debug.py:6
Replacing the event_loop fixture with a custom implementation is deprecated
and will lead to errors in the future.
If you want to request an asyncio event loop with a scope other than function
scope, use the "scope" argument to the asyncio mark when marking the tests.
If you want to return different types of event loops, use the event_loop_policy
fixture.
Two related issues are
Specifically, this line in event_loop shutdown fixes the issue
loop.run_until_complete(loop.shutdown_asyncgens())
I don't know why pytest-asyncio decides not to do this like in the standard asyncio
event_loop. #222 sounds like it has fixed these things but it appears it did not...
If instead of hacking the event_loop
, changing the test function into this
@pytest.mark.asyncio
async def test_earlystop():
data = gen()
async for x in data:
print(x)
if x > 8:
break
assert True
await data.aclose()
then all the issues are gone. But, of course, regular user should not need to do that await data.aclose()
!
I agree that async generators should be cleaned up properly. Pytest-asyncio is currently in the middle of transitioning away from the event_loop
fixture. You're seeing the DeprecationWarning, because users are supposed to get rid of their custom event_loop
implementations.
The current v0.23 release still has some issues that have to be ironed out (especially #706), in order to provide a proper migration path for users. Once everything is done, I'm sure this issue will be resolved as well.
My workaround above using aclose()
no longer makes it clean. I didn't deep dive.
This code:
Run it:
I was surprised to see
CancelledError
rather thanGeneratorExit
but it's OK. Now this code:Run it,
Now I don't understand why
CancelledError
was not raised, it appearsfinally
block was not executed, it appearsOf course, that "destroyed but it is pending" is also unpleasant to see.
Is there a bug in pytest-asyncio or am I missing something? I think this code should simply pass with no drama of any kind.