如何正确关闭Python Requests的HTTP连接?会话关闭后仍可访问的疑问
Python Requests Session关闭逻辑解析
核心差异:Session上下文管理器 vs 文件对象上下文管理器
你产生困惑的核心在于requests.Session的上下文管理器行为和文件对象完全不同:
- 文件对象在
with块结束后,不仅释放底层文件I/O资源,还会让对象进入不可用状态,调用读写方法会直接报错。 - 而
requests.Session的with块,仅在退出时自动调用session.close()方法——这个方法的作用是关闭Session持有的连接池中所有空闲TCP连接,但不会销毁Session对象本身,也不限制你访问对象属性或再次调用请求方法。
你的代码解析
看这段测试代码:
import requests with requests.Session() as s: s.post("https://example.com", headers={'Connection':'close'}) print(s) print(s) s.close() print(s)
三次打印都输出同一个Session对象的内存地址,原因如下:
print(s)只是输出对象的内存标识,只要对象未被Python垃圾回收,不管内部连接是否关闭都能正常打印。with块结束后,Session已经自动执行了close(),手动再调用一次s.close()属于重复操作,无额外效果。- 若此时用这个Session再次发送请求(比如
s.get("https://example.com")),请求依然会成功——因为Session在连接池为空时,会自动重新创建新的TCP连接。
另外要注意:你添加的headers={'Connection':'close'}是HTTP协议层面的指令,作用是告知服务器本次请求完成后关闭这条HTTP连接、不要复用。这和Session的连接池管理是两回事——它只会让当前请求的连接不被加入连接池复用,不会影响Session本身的状态。
验证Session连接是否真的关闭
若想确认Session的连接池是否已经关闭,可以查看其内部适配器的连接池状态:
import requests with requests.Session() as s: s.get("https://example.com") # 获取HTTPS适配器的连接池 adapter = s.adapters["https://"] print("with块内连接池数量:", len(adapter.poolmanager.pools)) # with块结束后,再次查看连接池 adapter = s.adapters["https://"] print("with块外连接池数量:", len(adapter.poolmanager.pools))
运行后会看到,with块外的连接池数量为0,说明Session的连接池确实已被清空关闭,但Session对象本身依然可用。
为什么文件对象会报错?
文件对象的with块结束后,底层文件描述符已被操作系统回收,对象的所有I/O方法都会检查描述符有效性,一旦无效就抛出ValueError。而Session的close()只是清理连接池,没有给对象添加“不可用”标记,所以不会触发报错。
内容的提问来源于stack exchange,提问作者Simon Ernesto Cardenas Zarate
相关产品推荐
相关产品推荐

