You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python 3.10.5使用aiohttp执行异步网络请求触发RuntimeError: Event loop is closed错误的解决方法求助

RuntimeError: Event loop is closed when using aiohttp with Python 3.10

Hey, I've dealt with this exact issue before when working with Python 3.10 and aiohttp on Windows! Let's walk through what's causing this and how to fix it.

The Problem

You've written a valid async HTTP request script using aiohttp, but when you run it, you get a RuntimeError: Event loop is closed exception from the Proactor event loop. Here's your code for reference:

#!/usr/bin/python
# coding=utf-8
import asyncio
import aiohttp

async def http_request(url, session):
    async with session.get(url) as response:
        return await response.text()

async def get_results(tasks):
    result = await asyncio.gather(*tasks)
    return result

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = [http_request(f"https://httpbin.org/delay/1?seq={x}", session) for x in range(3)]
        return await get_results(tasks)

if __name__ == '__main__':
    results = asyncio.run(main(), debug=False)
    for x in results:
        print(x)

And the error you're seeing:

Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001B9B9886950>
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 750, in call_soon
    self._check_closed()
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 515, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

What's Causing This?

On Windows, Python 3.10 uses the ProactorEventLoop by default. When asyncio.run() finishes executing your main coroutine, it immediately closes the event loop. However, aiohttp's ClientSession has background cleanup tasks (like closing connections) that haven't completed yet. These tasks try to run against the already closed loop, triggering the error.

Solutions

Here are three reliable ways to fix this:

1. Force the SelectorEventLoop (Quick Workaround)

Explicitly set the event loop policy to use WindowsSelectorEventLoopPolicy instead of the default Proactor loop. Add this code right after your imports:

from asyncio import WindowsSelectorEventLoopPolicy
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())

Your updated script will look like this:

#!/usr/bin/python
# coding=utf-8
import asyncio
from asyncio import WindowsSelectorEventLoopPolicy
import aiohttp

asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())

async def http_request(url, session):
    async with session.get(url) as response:
        return await response.text()

async def get_results(tasks):
    result = await asyncio.gather(*tasks)
    return result

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = [http_request(f"https://httpbin.org/delay/1?seq={x}", session) for x in range(3)]
        return await get_results(tasks)

if __name__ == '__main__':
    results = asyncio.run(main(), debug=False)
    for x in results:
        print(x)

This bypasses the Proactor loop's cleanup issues entirely.

2. Upgrade aiohttp (Permanent Fix)

The aiohttp team fixed this specific bug in version 3.8.2. Since you're on 3.8.1, just upgrade to the latest compatible version:

pip install --upgrade aiohttp

After upgrading, your original code should work without any changes. This is the best long-term solution.

3. Manually Manage the Event Loop

If you want full control over the loop lifecycle, replace asyncio.run() with manual loop setup and cleanup. This ensures all pending tasks finish before closing the loop:

if __name__ == '__main__':
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        results = loop.run_until_complete(main())
        for x in results:
            print(x)
    finally:
        # Clean up async generators and pending tasks
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()

This method gives the loop time to finish any background cleanup tasks before shutting down.

Which Should You Choose?

  • Upgrade aiohttp: Preferred if you can update dependencies, as it fixes the root cause.
  • SelectorEventLoop: Quickest fix if you can't upgrade.
  • Manual loop management: Best for advanced use cases where you need full control over the event loop.

内容的提问来源于stack exchange,提问作者ikool

火山引擎 最新活动