7

I'm writing python tests with pytest and have some async code I want to test so I installed the pytest-asyncio plugin. The async code uses aiohttp and running the tests I get the following warning/error/hint AFTER the test runs successfull.

========================================================================================================================================================================= test session starts =========================================================================================================================================================================
platform win32 -- Python 3.8.7, pytest-6.2.1, py-1.10.0, pluggy-0.13.1
rootdir: C:\Users\user\workspace\example\app
plugins: asyncio-0.14.0
collected 1 item                                                                                                                                                                                                                                                                                                                                                       

tests\test_something.py .

========================================================================================================================================================================== 1 passed in 1.22s ==========================================================================================================================================================================
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001D09DE4C310>
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

I am running the following code with python -m pytest

import aiohttp
import pytest

async def g():
    async with aiohttp.ClientSession() as session:
        async with session.get("https://www.w3schools.com/") as resp:
            pass


@pytest.mark.asyncio
async def test_connection():
    await g()

The warning after the test does not occur when I make a post to

...
async with session.post('http://httpbin.org/post', data=b'data') as resp:
...

Here is my requirements.txt

aiohttp==3.7.3
async-timeout==3.0.1
atomicwrites==1.4.0
attrs==20.3.0
certifi==2020.12.5
chardet==3.0.4
colorama==0.4.4
ibm-cloud-sdk-core==3.3.6
ibm-watson==5.1.0
idna==2.10
iniconfig==1.1.1
multidict==5.1.0
packaging==20.8
pluggy==0.13.1
py==1.10.0
PyJWT==2.0.0
pyparsing==2.4.7
pytest==6.2.1
pytest-asyncio==0.14.0
python-dateutil==2.8.1
requests==2.25.1
six==1.15.0
toml==0.10.2
typing-extensions==3.7.4.3
urllib3==1.26.2
websocket-client==0.48.0
websockets==8.1
yarl==1.6.3

What is the purpose of the warning that the Exception was ignored and why does it show up only in some cases?

hadamard
  • 401
  • 4
  • 16

1 Answers1

1

I had the exact same problem. The good news is that it looks like aiohttp has a fix for this problem. The bad news is that it won't be out until the 4.0 release (not sure when that is). Check out this issue (link to comment about the release): https://github.com/aio-libs/aiohttp/issues/1925#issuecomment-715977247

In the meantime, you can fix this (or at least this fixed it for me) but providing an event_loop fixture for the pytest-asyncio plugin. I added this to my conftest.py file:

import asyncio

import pytest

@pytest.fixture
def event_loop():
    loop = asyncio.get_event_loop()

    yield loop

    pending = asyncio.tasks.all_tasks(loop)
    loop.run_until_complete(asyncio.gather(*pending))
    loop.run_until_complete(asyncio.sleep(1))

    loop.close()

Basically insure everything has finished and then queue up and wait on a small sleep event. From the linked issue it appears that only the extra sleep line is all that is required, but I figured that if I was going to do something like this for all my async tests I would just go ahead and try get as clean a shutdown post-test as possible.

Craig Kelly
  • 3,776
  • 2
  • 18
  • 17