简单描述执行流程 🌟
Q:能简单描述一下发送一个requests.get(url)
请求时,在requests库内部的主要执行流程吗?(从调用get
方法到收到响应)
- 入口委托:
get()
方法内部调用requests.request('GET', url)
。- Session 接管:
request()
方法会获取或隐式创建一个Session
对象,并调用其request()
方法。Session
是核心,负责管理 Cookies、连接池复用和全局配置。- 请求准备:
Session
将传入的参数(URL、headers、params 等)合并、编码,构建成一个标准的PreparedRequest
对象。- 适配器与发送:
Session
根据 URL 协议 (http/https) 选择对应的HTTPAdapter
。HTTPAdapter
利用底层的urllib3
连接池 获取一个到目标服务器的连接(或新建),然后发送PreparedRequest
。- 处理响应:
- 处理重定向: 如果响应是重定向 (3xx) 且允许 (
allow_redirects=True
),会自动处理重定向链,直到获得最终响应。- 构建响应: 将
urllib3
的原始响应封装成requests.Response
对象,设置状态码、头信息、Cookies (更新Session
)、历史记录等。- 返回结果: 最终
Response
对象返回给调用者。- 释放资源: 通过
with requests.Session() as request:
显式使用上下文管理器,确保在退出时自动调用request.close()
,释放底层的urllib3
连接池资源,避免连接泄漏。
Session对象的作用
Q:Session 对象 (requests.Session
) 的主要作用是什么?它与直接调用 requests.get/post
在底层实现上有什么关键区别?
Session
是跨请求的持久化上下文管理器,核心解决 连接复用
、状态保持
和 配置继承
三大问题。
- 连接池复用:
- 底层通过
urllib3.PoolManager
复用 TCP 连接(尤其对同一主机发起多次请求时) - 避免重复 TCP 握手/TLS 协商,显著提升性能
- 底层通过
- 状态保持:
- 自动处理 Cookies:响应 Cookies 自动存储,后续请求自动携带
- 持久化认证:auth 参数在会话内持续有效
- 配置继承:
- 统一设置全局参数
- 支持全局
proxies
,hooks
,stream
等配置
注册适配器逻辑
Q:Session
如何通过 mount()
方法注册适配器?适配器与 URL 前缀的映射规则是什么?
- 创建 Session 对象时,自动注册默认的
https
和http
适配器。
mount
根据适配器的前缀长度来按序存储,前缀长的放前面,为了保证获取适配器时能按最长前缀优先匹配。
- 由于按序存储,获取
adapter
时,前缀匹配成功就直接返回,能获取到匹配的最长前缀适配器。