在 asyncio.run 外面建好 ClientSession,第二次调用 asyncio.run 时所有请求都报 RuntimeError: Session is closed,连接池跟着旧循环一起关了,第一次跑却是好的,重试也一样。日志里能对上时间点,这种反而好排。

ClientSession 绑定创建它时的那个事件循环,run 结束循环就关闭,连接池里的连接随之失效,复用之前不检查状态,再发请求自然报已关闭。这一点先确认清楚,后面就不用反复试。

async def main():
    async with aiohttp.ClientSession() as s:
        await fetch_all(s)
asyncio.run(main())

「aiohttp 会话跨循环」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。

报错里带路径的,先去看那个路径在不在、权限对不对。

处理上按这个顺序:session 在协程内部创建,跟着当次循环的生命周期走,不要提到外面;需要复用的把 run 只调用一次,业务都在同一个循环里跑;框架里用启动钩子建 session,关闭钩子里释放,别在请求处理函数里临时创建。

结果对不对很好判断,连续调用两次 run 都能正常返回,不再出现 Session is closed,连接池的状态也恢复正常。

作者 9823189