如何修复使用asyncio+aiohttp并行请求时的Session Closed错误?
问题
我尝试编写一个Python脚本,用于发起批量并行HTTP请求,以下是我的代码实现:
async def deleteLinkRecords(req_headers): async with aiohttp.ClientSession(trust_env=True) as session: idm_url = "https://example.com" tasks = [] for id in linkIdArr: del_url = idm_url + id tasks.append(make_request(session, del_url, req_headers)) results = await asyncio.gather(*tasks) print(results) async def make_request(session, url, req_headers): async with session.delete(url = url, headers = req_headers) as resp: return await resp.json() my_headers = { "Authorization": "Bearer XXX" } linkIdArr = ["abc", "def"....] asyncio.run(deleteLinkRecords(req_headers = my_headers))
运行该脚本时,我遇到了如下错误:
Traceback (most recent call last): File "C:\Users\mycode.py", line 48, in <module> asyncio.run(deleteLinkRecords(req_headers = my_headers)) File "C:\Users\AppData\Local\Programs\Python\Python39\lib\asyncio\runners.py", line 44, in run return loop.run_until_complete(main) File "C:\Users\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete return future.result() File "C:\Users\mycode.py", line 20, in deleteLinkRecords results = await asyncio.gather(*tasks) File "C:\Users\mycode.py", line 28, in make_requests async with session.delete(url = url, headers = req_headers) as resp: File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\aiohttp\client.py", line 1197, in __aenter__ self._resp = await self._coro File "C:\Users\AppData\Local\Programs\Python\Python39\lib\site-packages\aiohttp\client.py", line 428, in _request raise RuntimeError("Session is closed") RuntimeError: Session is closed
修复方案
核心问题
代码缩进错误导致await asyncio.gather(*tasks)跑到了async with aiohttp.ClientSession的上下文之外。当上下文管理器退出时,session会被立即关闭,此时再执行任务里的请求就会触发"Session is closed"错误。
修正后的完整代码
import asyncio import aiohttp async def deleteLinkRecords(req_headers): async with aiohttp.ClientSession(trust_env=True) as session: idm_url = "https://example.com" tasks = [] for link_id in linkIdArr: # 避免使用内置关键字id作为变量名 del_url = idm_url + link_id tasks.append(make_request(session, del_url, req_headers)) # 将gather调用放在async with代码块内部,确保session在请求执行期间保持打开 results = await asyncio.gather(*tasks) print(results) async def make_request(session, url, req_headers): async with session.delete(url=url, headers=req_headers) as resp: return await resp.json() my_headers = { "Authorization": "Bearer XXX" } linkIdArr = ["abc", "def"] # 补充完整的ID列表 asyncio.run(deleteLinkRecords(req_headers=my_headers))
额外优化点
- 避免使用Python内置关键字
id作为循环变量名,改用link_id避免潜在问题。 - 补充了缺失的
asyncio和aiohttp导入语句,确保脚本能正常运行。 - 统一了代码缩进风格,提升可读性。
内容的提问来源于stack exchange,提问作者RKodakandla
相关产品推荐
相关产品推荐

