返回

pip安装Python包时的SSL错误

在使用 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/...

问题定位

发生这种情况的一个常见原因是:设置了系统代理,且代理不支持 HTTPS,而此时 pip 读取了系统代理后使用了 HTTPS 协议下载。

CFW等软件一般会通过修改 Windows 注册表的 计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings下的ProxyServer 来配置代理服务器地址端口以及ProxyEnable

而 Python 3.7/3.8 版本的 pip 使用的urllib标准库,其request.py默认会读取系统代理配置,自动配置代理,但忽略了代理服务器不支持 HTTPS 的情况。

解决方法

要解决这个问题,有这几种方法:

  • 配置代理软件的 HTTPS 代理
  • 用TUN模式接管流量,实现隐形代理
  • 通过 pip 配置文件设置代理
  • 修改Python内置库,修复代理协议问题

前两种方法和使用的不同软件有关。

通过配置文件设置代理是最简单的方法,除了需要将代理地址硬编码到配置文件,屏蔽掉自动检测代理功能外,不会对其他软件产生影响;还可以通过一个小工具修复 Python 内置库的代理协议问题,强制将自动检测的代理协议改为 HTTP,这样能保留自动检测代理的功能。

接下来介绍后两种方法。

1. 设置 pip.ini

通过在用户目录下创建pip.ini文件,设置代理,即:

  • 对于 Windows,在目录%APPDATA%\pip(Windows)下创建pip.ini文件

  • 对于 Linux,在目录~/.config/pip/下创建pip.conf文件

向文件写入或追加内容:

[global]
proxy=http://127.0.0.1:7897

保存文件并重启终端,再次使用pip install,即可正常下载。

2. 修改内置库

修改 Python 内置库,修复代理协议问题。

我写了一个小工具并上传到了 PYPI,可以自动修改 Python 内置库的一处代理协议问题,经过测试(截止到本文发布时)会发生此问题的 Python 3.7/3.8 版本都可以成功修复。

首先确认当前环境是出现 HTTPS 代理问题的环境,然后在关闭代理的情况下安装此只有8KB大小的工具:

pip install pytool-proxy-fix

然后运行工具:

pytool-proxy-fix

之后会自动检测当前环境的 HTTPS 协议代理问题,通过强制设置urllib库自动转换代理时只使用 HTTP 协议,来修复代理协议问题。

结语

相比硬编码代理地址到配置文件,我更喜欢通过此工具进行修复,因为这样可以保留代理自动检测的功能。

文中提到的pytool-proxy-fix工具由我自己开发,其基于自由度最高的 MIT 协议开源,允许转载或二次开发,但必须注明原作者信息

Reference