使用 pip 安装 Python 包时,有时会遇到 SSL 错误,导致依赖无法下载。控制台输出类似:
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLZeroReturnError(6, '
TLS/SSL connection has been closed (EOF) (_ssl.c:1149)'))': /simple/...
日志冗长,原因却往往并不复杂。
问题定位
较常见的情况是:系统已配置代理,但该代理主要支持 HTTP;pip 仍将系统代理当作可用于 HTTPS 的通道。
Clash for Windows 等软件,通常会修改 Windows 注册表
计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
中的ProxyServer与ProxyEnable。
在 Python 3.7 / 3.8 中,pip 依赖的 urllib 会默认读取系统代理,却较少校验代理是否真正支持 HTTPS。连接中途被关闭后,便表现为上述 SSLZeroReturnError。
处理方式
可考虑以下途径:
- 完整配置代理软件的 HTTPS 代理
- 使用 TUN 模式在更底层接管流量
- 在 pip 配置文件中写明代理地址
- 调整 Python 内置库中的代理协议选择逻辑,使自动检测时仅使用 HTTP
前两项与具体代理软件相关,此处不展开。后两项与软件种类关系较小,记录如下。
1. 编写 pip 配置
在用户目录创建配置文件并指定代理:
- Windows:
%APPDATA%\pip\pip.ini - Linux:
~/.config/pip/pip.conf
端口请按本机代理设置修改:
[global]
proxy=http://127.0.0.1:7897
保存后重新打开终端,再执行 pip install,一般即可恢复正常。
该方式只影响 pip,影响面较小。代价是代理地址固定:更换端口需改配置,系统代理的自动检测也基本失效。
2. 修正内置库行为
若不愿在配置中写死代理,可使用我放在 PyPI 上的小工具 pytool-proxy-fix(GitHub)。包体积约 8KB,作用单一:使 urllib 在自动应用系统代理时仅使用 HTTP,避免误走 HTTPS。
本机测试中,发文时仍会触发该问题的 Python 3.7 / 3.8 均可修复。
请先确认当前环境确为「系统代理开启且 pip 报 SSL 错误」,并在关闭代理后安装:
pip install pytool-proxy-fix
pytool-proxy-fix
执行后会修改相应的协议选择逻辑。之后可重新开启代理,并继续使用自动检测。
若只求尽快恢复安装,使用 pip.ini / pip.conf 即可。若希望保留系统代理的自动检测,可优先考虑 pytool-proxy-fix。该工具以 MIT 协议开源,允许使用与修改;转载或二次开发时请注明原作者。