DEBUG.WIKI
晚安云;香港 CN2 ¥15/月
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →

aiohttp 第二次请求报 float 与 NoneType 无法比较

aiohttp 3.14.3 接受 keepalive_timeout=None,却在复用连接时触发 TypeError。核对连接器配置,使用数值超时或包含修复的正式版本,区分无限空闲与关闭复用。

同一个 ClientSession 第一次请求正常,第二次访问相同主机却报下面的异常,先看 traceback 是否落在 aiohttp/connector.py 的 _get():

TypeError: '<=' not supported between instances of 'float' and 'NoneType'

aiohttp 3.14.3 中,TCPConnector(keepalive_timeout=None) 能通过构造检查,但取出池中连接时仍计算“空闲时间是否小于等于超时值”。右边是 None,比较便失败。第一次请求需要新建连接,没有走到这次复用判断,因此可能成功。

先确认 None 是从哪里传进来的

检查项目创建 TCPConnector 的位置,以及把环境变量或配置文件转换为参数的那一层。缺失配置被转换成 None,与根本不传 keepalive_timeout 不是一回事。3.14.3 在省略该参数时使用 15 秒;显式传入 None 会保留到连接池内部。

这也不是 ClientTimeout(total=None) 的总请求超时问题。两者控制的对象不同,改总超时不会修正连接器里的比较。

如果业务只需要正常复用,并不需要无限保留空闲连接,可以省略该参数,或给出经过项目确认的数值。下面是连接器配置示意,应在现有异步入口中创建,继续由原来的 session 生命周期管理关闭:

import aiohttp

connector = aiohttp.TCPConnector(keepalive_timeout=15.0)

15 秒是示例,实际值需结合服务端空闲连接策略。更换正在使用的 session 前,先让已有请求正常结束并关闭旧 session,不能只改一个配置对象就认为池中连接都已替换。

需要 None 的语义时,更新到已修复实现

aiohttp 3.14.4 的正式实现已把 None 单独处理:连接只要仍被视为已连接,就不会仅因空闲时间过长而被淘汰。当前正式 3.14.5 也保留这项处理。核对依赖约束和 Python 支持范围后,选择包含该修复的兼容正式版本,更新锁文件并重新部署;这两个版本要求 Python 3.10 或更高。

None 不保证远端永远保持连接,也不代表主动探测连接状态。对端关闭的连接仍可能在下一次访问该主机时才被清理。没有必要时,不宜为了避开一个比较错误而把所有连接改成无限空闲。

如果意图是每次请求后关闭连接,应使用 TCPConnector(force_close=True),不要把 keepalive_timeout=None 当作关闭复用的开关。关闭复用会增加建连成本;也不能同时给 force_close=True 和数值形式的 keepalive_timeout。

验收要覆盖连接确实被复用的情况

在自己的受控 HTTP 服务上,连续请求同一主机,并完整读取响应正文,让连接能够返回池中;核对第二次及后续请求,不只观察第一次返回 200。另检查服务端主动关连接和短暂空闲后的请求能否按原来的异常处理完成。

若仍在 _get() 比较处失败,检查运行进程实际加载的 aiohttp 版本、连接器创建参数与部署环境,而不是只看开发机的锁文件。若堆栈已变成读取超时或连接被重置,应按那个新的故障分支处理,不能据此继续扩大本问题的版本范围。