当前位置: 首页 > news >正文

Requests Session 内部源码分析

在 Python 生态中,requests是应用最广泛的 HTTP 客户端库,而Session类是其实现高性能、状态化请求的核心。多数开发者熟知它可以持久化 Cookie、复用 TCP 连接,却很少深入其内部实现。本文基于 requests 官方源码,从初始化、请求构建、发送链路、连接池管理到资源释放,完整拆解 Session 的内部运行机制。

一、Session 类的整体定位与初始化

1.1 核心定位

Session是 requests 状态管理的核心载体,官方定义其三大核心能力:Cookie 持久化、连接池复用、全局配置统一管理。值得注意的是,我们日常使用的requests.get()requests.post()等顶层 API,本质上都是临时创建一个 Session 实例、执行请求后立即销毁,这也是单次请求性能弱于复用 Session 的根本原因。

Session 类的继承关系非常简洁:

python

运行

class Session(SessionRedirectMixin):

它仅继承了SessionRedirectMixin,后者封装了重定向处理的通用逻辑,将重定向能力从核心会话类中解耦出来。

1.2 初始化核心逻辑

__init__方法完成了 Session 所有基础状态的初始化,核心代码如下:

python

运行

def __init__(self): # 会话级默认请求头,大小写不敏感 self.headers = default_headers() # 认证信息,支持元组或自定义Auth对象 self.auth = None # 全局代理配置 self.proxies = {} # Cookie 容器,基于 cookielib.CookieJar 封装 self.cookies = cookiejar_from_dict({}) # 请求钩子,默认仅包含 response 事件 self.hooks = default_hooks() # 默认查询参数 self.params = {} # SSL 证书校验开关 self.verify = True # 客户端证书路径 self.cert = None # 流式响应开关 self.stream = False # 最大重定向次数 self.max_redirects = 30 # 是否信任系统环境变量(代理等配置) self.trust_env = True # 适配器有序字典,核心:协议 -> 传输适配器映射 self.adapters = OrderedDict() # 默认挂载 HTTP/HTTPS 适配器,底层对接 urllib3 self.mount('https://', HTTPAdapter()) self.mount('http://', HTTPAdapter())

初始化过程中有两个关键设计:

  1. 配置分层设计:所有请求相关的配置都有会话级默认值,后续请求可传入单次参数覆盖,实现 "全局默认 + 单次定制" 的灵活模式。
  2. 适配器模式:Session 本身不处理底层网络通信,而是通过adapters字典将不同协议的请求分发到对应传输适配器,默认的HTTPAdapter封装了 urllib3 的全部能力。

二、请求构建全流程:从 request () 到 PreparedRequest

Session 中所有 HTTP 方法(get/post/put 等)最终都会调用request()方法,这是请求构建的入口,其核心职责是完成 "原始参数 -> Request 对象 -> PreparedRequest 对象" 的两次转换。

2.1 request () 方法:参数聚合与初步封装

python

运行

def request(self, method, url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, hooks=None, stream=None, verify=None, cert=None, json=None): # 第一步:创建原始 Request 对象,仅做参数封装,无业务逻辑 req = Request( method=method.upper(), url=url, headers=headers, files=files, data=data or {}, json=json, params=params or {}, auth=auth, cookies=cookies, hooks=hooks, ) # 第二步:预处理请求,合并会话级配置,生成可发送的 PreparedRequest prep = self.prepare_request(req) # 第三步:合并环境配置(系统代理、SSL 配置等) proxies = proxies or {} settings = self.merge_environment_settings( prep.url, proxies, stream, verify, cert ) # 组装发送参数 send_kwargs = { 'timeout': timeout, 'allow_redirects': allow_redirects, } send_kwargs.update(settings) # 第四步:调用 send 方法发送预处理后的请求 resp = self.send(prep, **send_kwargs) return resp

2.2 prepare_request ():配置合并的核心

这是 Session 状态持久化的核心方法,负责将会话级配置与单次请求配置合并,生成最终可直接发送的PreparedRequest对象:

python

运行

def prepare_request(self, request): # 复制会话级 Cookie,作为基础 cookies = request.cookies if not cookies: cookies = self.cookies else: cookies = merge_cookies(self.cookies, cookies) # 生成 PreparedRequest 并依次执行预处理步骤 p = PreparedRequest() p.prepare( method=request.method.upper(), url=request.url, files=request.files, data=request.data, json=request.json, headers=merge_setting(request.headers, self.headers), auth=merge_setting(request.auth, self.auth), cookies=cookies, hooks=merge_hooks(request.hooks, self.hooks), ) return p

配置合并遵循请求级优先原则:单次请求传入的参数会覆盖会话级默认值,未传入的参数则继承会话配置。最终生成的PreparedRequest是一个无状态的、包含全部请求信息的可发送对象,这也是 requests 中 "请求构建" 与 "请求发送" 解耦的关键设计。

三、请求发送核心:send () 方法的执行链路

send()是 Session 的核心调度方法,接收预处理完成的PreparedRequest,完成适配器匹配、网络发送、Cookie 回写、钩子执行、重定向处理全流程Requests。

3.1 核心执行流程

python

运行

def send(self, request, **kwargs): # 1. 填充默认参数:未指定的参数使用会话级默认值 kwargs.setdefault('stream', self.stream) kwargs.setdefault('verify', self.verify) kwargs.setdefault('cert', self.cert) kwargs.setdefault('proxies', self.proxies) # 安全校验:只允许发送预处理后的 PreparedRequest if isinstance(request, Request): raise ValueError('You can only send PreparedRequests.') # 2. 根据 URL 匹配对应的传输适配器 adapter = self.get_adapter(url=request.url) # 3. 调用适配器发送请求,底层通过 urllib3 完成网络IO r = adapter.send(request, **kwargs) # 4. 执行响应钩子:用户自定义的 response 回调在此处触发 r = dispatch_hook('response', hooks, r, **kwargs) # 5. 从响应中提取 Cookie,回写到会话级 CookieJar extract_cookies_to_jar(self.cookies, request, r.raw) # 6. 重定向处理 if allow_redirects: # 迭代处理所有重定向,收集历史响应 history = [] for resp in self.resolve_redirects(r, request, **kwargs): history.append(resp) r.history = history return r

3.2 适配器匹配机制

get_adapter()实现了基于 URL 前缀的最长匹配规则:

python

运行

def get_adapter(self, url): # 按前缀长度倒序遍历,优先匹配更长的前缀 for prefix in sorted(self.adapters.keys(), reverse=True): if url.lower().startswith(prefix): return self.adapters[prefix]

这一设计让用户可以针对特定域名挂载自定义适配器,例如为https://api.internal.com挂载专用的内网适配器,实现精细化的传输层控制。

四、底层连接复用:HTTPAdapter 与 urllib3 连接池

Session 性能优势的核心是 TCP 连接复用,而这一能力完全由HTTPAdapter对接 urllib3 实现,Session 本身仅做调度。

4.1 HTTPAdapter 的核心职责

HTTPAdapter是 requests 定义的传输适配器标准实现,它桥接了 requests 的高层 API 与 urllib3 的底层连接池能力,核心初始化参数如下Requests:

  • pool_connections:缓存的连接池数量,默认 10,对应不同的 host:port
  • pool_maxsize:单个连接池内的最大连接数,默认 10
  • max_retries:连接失败重试次数,默认 0
  • pool_block:连接池耗尽时是否阻塞等待,默认 False

每个 Session 初始化时会创建两个独立的 HTTPAdapter 实例,分别处理 HTTP 和 HTTPS 请求,各自维护独立的连接池。

4.2 连接池复用逻辑

当 adapter 收到发送请求时,核心流程为:

  1. 根据 URL 的 scheme、host、port 生成唯一的连接池 key
  2. 从本地缓存中查找对应的连接池,不存在则新建
  3. 从连接池中取出一个空闲的 TCP 连接
  4. 若连接池无空闲连接且未达上限,则新建 TCP 连接
  5. 请求完成后,将连接放回连接池等待复用

这一机制保证了向同一主机发送多个请求时,底层 TCP 连接(含 TLS 握手)只会建立一次,大幅减少请求延迟,这也是高并发场景下必须使用 Session 的核心原因。

五、状态持久化:Cookie 管理机制

Session 的 Cookie 持久化基于 Python 标准库http.cookiejar.CookieJar实现,核心逻辑分为两步:

  1. 请求前合并:发送请求时,将会话级 Cookie 与单次请求 Cookie 合并,写入请求头
  2. 响应后回写:收到响应后,解析响应头中的 Set-Cookie,更新到会话级 CookieJar 中

关键代码位于send()方法中的extract_cookies_to_jar调用,它会自动处理 Cookie 的域名、路径、过期时间等规则,确保跨请求的 Cookie 状态一致。用户无需手动处理 Cookie 头,Session 会自动完成全生命周期管理。

六、资源管理:上下文管理器与 close 方法

由于底层维护了连接池,Session 使用完毕后必须正确释放资源,否则会造成连接泄漏,耗尽系统文件描述符。

6.1 上下文管理器实现

Session 实现了标准的上下文管理器协议,推荐使用with语句管理生命周期:

python

运行

def __enter__(self): return self def __exit__(self, *args): self.close()

6.2 close () 资源释放逻辑

python

运行

def close(self): """关闭所有适配器,释放全部连接池资源""" for adapter in self.adapters.values(): adapter.close()

adapter.close()会进一步调用 urllib3 连接池的清理方法,关闭所有空闲 TCP 连接,将资源归还操作系统。在高频请求场景中,若不调用 close 方法,连接会随对象被 GC 回收才释放,极易引发Too many open files错误。

七、扩展能力:钩子与自定义适配器

Session 设计了两个核心扩展点,满足高级定制需求:

  1. 钩子机制(Hooks):支持在response阶段注入自定义回调函数,可统一处理响应日志、异常校验、数据格式化等逻辑,钩子会在每次请求返回后、重定向处理前执行。
  2. 自定义适配器:通过mount()方法挂载自定义传输适配器,可实现自定义 DNS 解析、SOCKS5 代理、缓存策略、限流控制等能力,是 requests 生态扩展的核心入口。

总结

Requests Session 的设计体现了非常经典的分层架构思想:

  • 上层调度层:Session 类负责状态管理、配置合并、请求调度,不涉及底层网络
  • 中间适配层:HTTPAdapter 实现协议适配,桥接高层 API 与底层网络库
  • 底层能力层:urllib3 提供连接池、HTTP 协议实现、SSL 处理等核心网络能力

理解 Session 内部源码,不仅能帮助我们写出更高性能、更健壮的 HTTP 客户端代码,更能掌握 "配置分层、职责解耦、面向接口扩展" 的优秀库设计思路。在生产环境中,针对同一域名的批量请求,复用 Session 实例并配合上下文管理器管理资源,是 requests 性能优化的最基础也最有效的手段。

http://www.jsqmd.com/news/1255012/

相关文章:

  • 【LLM API安全设计红线】:从越权调用到Prompt注入,12类攻击面+OWASP最新防护清单
  • 2026 年阜阳中考落榜无法读高中,学习哪些技术专业就业更稳定?合肥优质技工院校专业解读 - cc江江
  • 深圳全品类黄金回收攻略!旧金碎金K金变现标准详解 - 一日一测评
  • 基于Transformer的风电功率预测算法优化与实践
  • PDF转Word排版乱了怎么修复?六大常见问题逐一调回原样
  • 2026 杭州主城名表回收实体店走访,上城湖滨门店真实行情横向对比 - 奢侈品回收探店ing
  • 2026大模型技术栈:架构演进与推理优化实战
  • 10款降AIGC工具测评:提升文本原创性的技术方案
  • 音乐节奏设计:从Cadence基础到DAW实战技巧
  • 能源垂类大模型:破解电力系统智能化转型难题
  • 专科生必备9款AI工具:高效学习与工作指南
  • 2026长沙网红打卡墙设计TOP5推荐|如何选择专业墙绘团队 - 中国远见品牌企业资讯
  • Magic Leap转型B2B:光波导与AI技术如何重塑AR智能眼镜未来
  • C++20 std::format 核心语法、类型安全与实战指南
  • 工业电机软启动柜实用价值解析:助力企业降本增效的关键设备 - 品牌优选官
  • AIGC工具原创性提升策略与十大官网工具评测
  • GSRA自注意力机制:几何校正与语义强化的视觉特征增强
  • TI DRV832x栅极驱动器:智能驱动与VDS过流保护实战解析
  • C#图形开发全攻略:从GDI+、WPF到GPU三维渲染实战
  • 收藏必备!小白程序员快速入门大模型Agent,引领AI新时代
  • 大模型蒸馏实战指南:从原理到部署的完整技术解析
  • PS 怎么去掉图片水印不损坏原图?4 种高效方法适配各类复杂水印
  • C++实战集成Speex音频重采样:从原理到实时语音处理应用
  • RNN与LSTM:序列建模的核心原理与工程实践
  • 【AI大模型参数解密手册】:20年架构师亲授17类核心参数真实含义与调优陷阱
  • AI Agent开发学习路径与核心技术解析
  • 2027年自主机器人作战单元:法国“潘德拉贡”(Pendragon)项目
  • 产业智能化转型:关键技术、应用场景与实施路径
  • 系统集成架构:让“信息孤岛“连成大陆
  • Qwen3.5-397B MoE模型:长文本处理与混合专家架构解析