一、问题现象
在 Windows 系统上使用 Anaconda 的 Python 环境执行 pip install 时,无论指定哪个 PyPI 镜像源,均报出相同的 SSL 握手错误:
使用清华镜像源:
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(142, '[ASN1: NOT_ENOUGH_DATA] not enough data (_ssl.c:3992)'))': /simple/gradio-imageslider/
ERROR: Could not find a version that satisfies the requirement gradio_imageslider (from versions: none)
ERROR: No matching distribution found for gradio_imageslider
使用阿里云镜像源:
Looking in indexes: https://mirrors.aliyun.com/pypi/simple/
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(142, '[ASN1: NOT_ENOUGH_DATA] not enough data (_ssl.c:3992)'))': /pypi/simple/gradio-imageslider/
ERROR: Could not find a version that satisfies the requirement gradio_imageslider (from versions: none)
ERROR: No matching distribution found for gradio_imageslider
关键发现: 清华源和阿里云源报完全相同的错误,说明这不是某个镜像源的问题,而是本地环境的 SSL/TLS 连接本身存在底层故障。
二、初步排查:切换镜像源均失败
为定位问题,依次尝试了以下镜像源,均报相同错误:
| 镜像源 | 命令 | 结果 |
|---|---|---|
| 清华源 | pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
SSL 握手失败 |
| 阿里云 | pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ |
SSL 握手失败 |
| 中科大 | pip install -r requirements.txt -i https://pypi.mirrors.ustc.edu.cn/simple |
SSL 握手失败 |
结论: 所有国内镜像源均失败,问题不在镜像源,而在本地环境的 SSL 连接层。
三、深入诊断
3.1 检查代理环境变量
在 Anaconda Prompt 中检查所有代理相关环境变量:
echo %https_proxy%
echo %http_proxy%
echo %ALL_PROXY%
结果: 所有代理环境变量均为空(未设置),排除代理干扰。
3.2 检查 Python 和 OpenSSL 版本
python -c "import sys, ssl; print('Python版本:', sys.version.split()[0]); print('OpenSSL版本:', ssl.OPENSSL_VERSION)"
结果:
| 项目 | 版本 | 状态 |
|---|---|---|
| Python | 3.10.0 | 正常 |
| OpenSSL | 3.6.3 | 正常(版本很新) |
OpenSSL 版本为 3.6.3,不是老旧版本,排除因 OpenSSL 版本过旧导致 TLS 协议不支持的问题。
3.3 直接测试 SSL 连接
在 Anaconda Prompt 中执行以下命令,直接测试能否与 pypi.org 建立 SSL 连接:
python -c "import ssl,socket; ctx=ssl.create_default_context(); s=ctx.wrap_socket(socket.socket(),server_hostname='pypi.org'); s.settimeout(15); s.connect(('pypi.org',443)); print('SSL连接成功'); s.close()"
报错结果:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "E:\miniconda3\envs\deepanythingv2\lib\ssl.py", line 770, in create_default_context
context.load_default_certs(purpose)
File "E:\miniconda3\envs\deepanythingv2\lib\ssl.py", line 591, in load_default_certs
self._load_windows_store_certs(storename, purpose)
File "E:\miniconda3\envs\deepanythingv2\lib\ssl.py", line 583, _load_windows_store_certs
self.load_verify_locations(cadata=certs)
ssl.SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data (_ssl.c:3992)
关键信息: 错误发生在 ssl.py 的调用链中:
create_default_context()
→ load_default_certs()
→ _load_windows_store_certs()
→ load_verify_locations(cadata=certs) ← 在此处崩溃
这说明 Python 在从 Windows 证书库(Certificate Store)读取根证书时,遇到了损坏的证书数据,导致 SSL 上下文初始化直接崩溃。
四、根因分析
综合以上诊断结果,问题的根本原因如下:
Windows 系统证书存储(Certificate Store)已损坏。
具体说明:
- 不是缺 OpenSSL: 环境中的 OpenSSL 3.6.3 版本很新,运行正常。
- 不是镜像源问题: 清华、阿里云、中科大等多个镜像源均报相同错误。
- 不是代理干扰: 所有代理环境变量均为空。
- 错误定位: 崩溃发生在
ssl.SSLContext._load_windows_store_certs()方法内部,Python 尝试从 Windows 系统证书库加载根证书时,读取到了损坏的 ASN.1 编码数据,触发ASN1: NOT_ENOUGH_DATA异常。 - 触发条件: 当 Python 执行
ssl.create_default_context()(pip 内部会调用)时,会自动加载系统证书库中的所有根证书,损坏的证书数据导致加载过程崩溃。
五、解决方案
方案一:创建新的 conda 环境并使用 Python 3.11(推荐)
原理: Python 3.11 对 Windows 证书库损坏的情况做了容错处理------当遇到损坏的证书数据时,会跳过该证书继续加载,而不是直接崩溃。而当前环境使用的 Python 3.10.0(2021年11月构建)没有此容错机制。
操作步骤:
在 Anaconda Prompt 中依次执行:
conda create -n daV2 python=3.11 -y
conda activate daV2
pip install --upgrade pip
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
说明:
conda create -n daV2 python=3.11 -y:创建名为daV2的新环境,使用 Python 3.11-y参数表示自动确认,无需手动输入 y- 新环境中的 Python 3.11 会自动跳过损坏的证书,SSL 连接恢复正常
- 之后所有 pip install 命令均可正常使用
成功率: 较高(Python 3.11 的容错机制能解决绝大多数证书库损坏场景)
方案二:使用 sitecustomize.py 修补 ssl 模块(备选)
原理: 在 Python 的 site-packages 目录中创建一个 sitecustomize.py 文件,Python 启动时会自动执行该文件。在其中重写 _load_windows_store_certs 方法,捕获损坏证书的异常并跳过,从而让 SSL 连接恢复正常。
操作步骤:
- 用记事本打开路径
E:\miniconda3\envs\deepanythingv2\Lib\site-packages\ - 新建文件
sitecustomize.py - 粘贴以下内容并保存:
python
import ssl
_original = ssl.SSLContext._load_windows_store_certs
def _safe_load_windows_store_certs(self, storename, purpose):
certs = bytearray()
try:
from ssl import _windows
for cert, encoding, trust in _windows.enum_certificates(storename):
if encoding == "x509_asn":
if trust is True or purpose.oid in trust:
try:
certs.extend(cert)
except Exception:
pass
except Exception:
pass
try:
self.load_verify_locations(cadata=certs)
except ssl.SSLError:
pass
return certs
ssl.SSLContext._load_windows_store_certs = _safe_load_windows_store_certs
-
重新打开一个 Anaconda Prompt(需要刷新环境)
-
验证修复是否生效:
python -c "import ssl; ctx=ssl.create_default_context(); print('SSL恢复正常!')"
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
说明:
- 该方法直接修补当前环境的 ssl 模块,不依赖 Python 版本
- 成功率接近 100%
- 缺点:属于"打补丁"方式,系统证书库本身仍然是损坏的
成功率: 接近 100%
方案三:修复 Windows 系统证书存储(根治方案)
原理: 通过 Windows 系统自带的修复工具,修复损坏的系统证书库文件,从根本上解决问题。
操作步骤:
-
以管理员身份打开命令提示符(CMD):
- 按
Win + S,输入cmd - 右键点击"命令提示符",选择"以管理员身份运行"
- 按
-
执行系统文件检查:
sfc /scannow
-
执行 DISM 修复:
DISM /Online /Cleanup-Image /RestoreHealth
-
等待修复完成(可能需要较长时间),然后重启电脑
-
重启后,如果之前使用了方案二(创建了
sitecustomize.py),可以将其删除:del E:\miniconda3\envs\deepanythingv2\Lib\site-packages\sitecustomize.py
说明:
- 这是根治方案,修复后系统层面的 SSL 连接将完全恢复正常
- 但修复成功率取决于系统损坏程度,有时 sfc 和 DISM 可能无法修复证书库
- 如果方案一和方案二已能满足需求,可以暂不执行此方案
成功率: 取决于系统损坏程度
六、为什么不能通过 pip 安装 OpenSSL 来修复
部分用户可能会想:"既然问题是 SSL 证书相关的,能不能通过 pip install openssl 来修复?" 答案是不行,原因如下:
- OpenSSL 已经存在且版本正常: 环境中的 OpenSSL 3.6.3 版本很新,运行正常。
- 问题不在 OpenSSL 库本身: 问题出在 Windows 证书库中的数据损坏,而非 OpenSSL 库缺失或过时。
- 死循环问题:
pip install需要通过 HTTPS 下载包 → HTTPS 依赖 SSL → SSL 依赖证书库加载 → 证书库损坏 → SSL 初始化失败 → pip 无法连接任何服务器 → 无法安装任何东西。这是一个无法自行解开的死循环。 - OpenSSL 是系统级 C 库: 它不是 Python 包,无法通过 pip 安装。即使 PyPI 上有名为
openssl的包,也只是一个 Python 封装,底层依然依赖系统证书库。
七、问题总结
错误信息速查
| 项目 | 内容 |
|---|---|
| 错误类型 | ssl.SSLError |
| 错误代码 | [ASN1: NOT_ENOUGH_DATA] not enough data (_ssl.c:3992) |
| 错误位置 | ssl.py → _load_windows_store_certs() → load_verify_locations(cadata=certs) |
| 根本原因 | Windows 系统证书存储(Certificate Store)中有损坏的证书数据 |
| 影响范围 | 所有依赖 Python SSL 模块的操作(pip install、requests、urllib 等) |
| 触发条件 | 执行 ssl.create_default_context() 时自动加载系统证书库 |
解决方案对比
| 方案 | 操作难度 | 成功率 | 说明 |
|---|---|---|---|
| 方案一:新建 conda 环境 + Python 3.11 | 简单 | 较高 | 新版 Python 自带容错,推荐首选 |
| 方案二:sitecustomize.py 修补 ssl 模块 | 中等 | 接近 100% | 直接修补,立竿见影 |
| 方案三:修复 Windows 证书库 | 较复杂 | 取决于系统 | 根治方案,修复系统层面问题 |
快速决策指南
是否需要立即恢复 pip 使用?
├── 是 → 先执行方案一(新建 Python 3.11 环境)
│ ├── 成功 → 问题解决 ✅
│ └── 失败 → 执行方案二(sitecustomize.py 修补)✅
└── 否(暂时不急)→ 执行方案三(修复 Windows 证书库)