【BUG已解决】pip install 出现 SSL: CERTIFICATE_VERIFY_FAILED 报错的解决方案
前言
本文主要介绍了使用 pip 安装 Python 包时出现SSL: CERTIFICATE_VERIFY_FAILED证书验证失败错误的完整排查过程和解决方案,涵盖企业网络代理、系统证书缺失、Python证书路径配置、镜像源切换等多种场景,希望能帮助大家彻底解决这个困扰众多开发者的经典问题。
1. 问题描述
1.1 完整报错信息
Collecting requests Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1006)'))': /simple/requests/ WARNING: Retrying (Retry(total=3, ...)) after connection broken by 'SSLError(...)' ERROR: Could not find a version that satisfies the requirement requests ERROR: No matching distribution found for requestsmacOS 特有的报错形式:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1002)1.2 具体现象
- 执行
pip install 任意包名,出现证书验证失败 - 公司网络下更容易出现(企业防火墙做了 HTTPS 中间人代理)
- 刚安装的 macOS 系统上运行 Python 脚本涉及 HTTPS 请求时报错
- 之前能正常 pip install,某次系统更新后突然报错
- 用浏览器访问 pypi.org 是正常的,但 pip 命令行报错
1.3 触发场景归类
| 场景 | 环境特征 |
|---|---|
| 企业/学校网络 | 防火墙/安全网关做 SSL 中间人代理 |
| macOS 新装 Python | Python.org 官方安装包未正确配置证书 |
| 系统证书链过期 | 长期未更新系统根证书 |
| pip 自身版本过旧 | 旧版 pip 的 SSL 处理逻辑有缺陷 |
| VPN/代理软件冲突 | 部分 VPN 软件解密 HTTPS 流量 |
2. 原因分析
2.1 SSL 证书验证的基本原理
客户端(pip) 发起 HTTPS 请求 ↓ 服务器(pypi.org) 返回证书链 ↓ 客户端验证证书链是否可信 - 查找本地的"根证书授权机构(CA)"列表 - 验证服务器证书是否由可信CA签发 ↓ 验证通过 → 建立安全连接 → 正常下载 验证失败 → SSL: CERTIFICATE_VERIFY_FAILEDunable to get local issuer certificate这句话的意思是:客户端本地找不到能验证服务器证书链的根证书。
2.2 五大根本原因
| # | 原因 | 说明 | 占比 |
|---|---|---|---|
| 1 | macOS Python 证书未初始化 | python.org 官方安装包需要手动运行证书安装脚本 | 30% |
| 2 | 企业网络 HTTPS 中间人代理 | 防火墙自签名证书替换了真实证书 | 25% |
| 3 | 系统根证书过期/缺失 | 老旧系统长期未更新CA证书库 | 20% |
| 4 | certifi 包版本过旧 | Python 用的 certifi 证书包没跟上最新CA | 15% |
| 5 | 代理软件解密流量 | Charles/Fiddler等抓包工具改写了证书 | 10% |
2.3 macOS 特有问题的根源
macOS 从 python.org 下载安装的 Python(非系统自带),使用的是独立的 SSL 证书体系,不会自动使用 macOS 系统的钥匙串证书。安装 Python 后,如果没有额外运行证书安装脚本,pip 就无法验证任何 HTTPS 网站的证书。
3. 解决方案
3.1 方案一:macOS 运行官方证书安装脚本(macOS 专属,最常见问题的解法)
# 找到 Python 安装目录下的证书安装脚本 # 通常在 /Applications/Python 3.x/ 目录下 open "/Applications/Python 3.11/Install Certificates.command"或者直接在终端运行:
# 找到当前 Python 版本 python3 --version # 运行对应版本的证书安装脚本(路径根据实际版本调整) /Applications/Python\ 3.11/Install\ Certificates.command如果找不到这个文件,手动执行等效操作:
pip install --upgrade certifi python3 -c "import certifi; print(certifi.where())" # 输出 certifi 证书文件路径 # 设置 SSL_CERT_FILE 环境变量指向该路径 export SSL_CERT_FILE=$(python3 -c "import certifi; print(certifi.where())") echo 'export SSL_CERT_FILE=$(python3 -c "import certifi; print(certifi.where())")' >> ~/.zshrc source ~/.zshrc3.2 方案二:升级 certifi 和 pip 本身
# 升级 pip python -m pip install --upgrade pip # 升级 certifi(提供最新的根证书列表) pip install --upgrade certifi # 重新尝试安装 pip install requests3.3 方案三:使用 --trusted-host 参数临时绕过验证(企业网络快速方案)
pip install requests \ --trusted-host pypi.org \ --trusted-host files.pythonhosted.org \ --trusted-host pypi.python.org永久配置(写入 pip 配置文件):
# 创建/编辑 pip 配置文件 # macOS/Linux: ~/.pip/pip.conf 或 ~/.config/pip/pip.conf # Windows: %APPDATA%\pip\pip.ini mkdir -p ~/.pip cat > ~/.pip/pip.conf << 'EOF' [global] trusted-host = pypi.org files.pythonhosted.org pypi.python.org EOF⚠️ 安全提示:
--trusted-host会跳过 SSL 证书验证,存在安全风险,仅建议在可信的企业内网环境临时使用,不要在公共网络长期使用此方案。
3.4 方案四:企业网络配置自定义 CA 证书(更安全的企业方案)
如果你的公司网络使用了 SSL 中间人代理(如 Zscaler、Blue Coat),正确做法是安装公司提供的根证书:
# 1. 从 IT 部门获取企业根证书文件(通常是 .crt 或 .pem 格式) # 2. 找到 certifi 的证书文件路径 python -c "import certifi; print(certifi.where())" # 输出示例: /usr/local/lib/python3.11/site-packages/certifi/cacert.pem # 3. 将企业证书追加到 certifi 的证书包中 cat /path/to/company_ca.crt >> $(python -c "import certifi; print(certifi.where())") # 4. 重新测试 pip install requests3.5 方案五:使用国内镜像源(同时解决网络慢的问题)
有些证书问题实际上与访问 pypi.org 的网络环境有关,切换到国内镜像可以顺带绕开:
# 临时使用清华镜像 pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple # 永久设置镜像源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 其他常用国内镜像 # 阿里云: https://mirrors.aliyun.com/pypi/simple/ # 腾讯云: https://mirrors.cloud.tencent.com/pypi/simple # 豆瓣: https://pypi.doubanio.com/simple/3.6 方案六:更新系统根证书(Linux)
# Ubuntu/Debian sudo apt-get update sudo apt-get install --reinstall ca-certificates # CentOS/RHEL sudo yum reinstall ca-certificates sudo update-ca-trust force-enable3.7 方案七:Windows 更新系统证书
# Windows 通常通过 Windows Update 自动更新根证书 # 手动检查更新 Get-WindowsUpdate # 或者直接安装最新的 Visual C++ 和 .NET Framework 运行库 # 这些更新通常包含证书库的更新3.8 方案八:临时禁用 SSL 验证(仅供调试,生产环境禁用)
在 Python 代码内部(非 pip 命令行)临时禁用:
import ssl import urllib.request # ⚠️ 仅用于本地调试,生产环境切勿使用 ssl._create_default_https_context = ssl._create_unverified_context或使用 requests 库:
import requests # ⚠️ 同样仅用于调试 response = requests.get("https://example.com", verify=False)4. 排查诊断脚本
# diagnose_ssl.py import ssl import certifi import requests print("=== SSL 诊断报告 ===") print(f"OpenSSL 版本: {ssl.OPENSSL_VERSION}") print(f"certifi 证书路径: {certifi.where()}") try: response = requests.get("https://pypi.org", timeout=10) print(f"✅ 连接 pypi.org 成功: {response.status_code}") except requests.exceptions.SSLError as e: print(f"❌ SSL 验证失败: {e}") except Exception as e: print(f"❌ 其他错误: {e}") # 检查证书文件是否存在 import os cert_path = certifi.where() if os.path.exists(cert_path): print(f"✅ 证书文件存在,大小: {os.path.getsize(cert_path)} bytes") else: print(f"❌ 证书文件不存在: {cert_path}")运行诊断:
python diagnose_ssl.py6. 排查诊断脚本
# diagnose_ssl.py import ssl import certifi import requests print("=== SSL 诊断报告 ===") print(f"OpenSSL 版本: {ssl.OPENSSL_VERSION}") print(f"certifi 证书路径: {certifi.where()}") try: response = requests.get("https://pypi.org", timeout=10) print(f"✅ 连接 pypi.org 成功: {response.status_code}") except requests.exceptions.SSLError as e: print(f"❌ SSL 验证失败: {e}") except Exception as e: print(f"❌ 其他错误: {e}") # 检查证书文件是否存在 import os cert_path = certifi.where() if os.path.exists(cert_path): print(f"✅ 证书文件存在,大小: {os.path.getsize(cert_path)} bytes") else: print(f"❌ 证书文件不存在: {cert_path}")运行诊断:
python diagnose_ssl.py7. 各方案适用场景总结
| 方案 | 适用场景 | 安全性 | 推荐度 |
|---|---|---|---|
| macOS证书脚本 | macOS python.org安装的Python | ✅ 安全 | ⭐⭐⭐⭐⭐ |
| 升级certifi | 所有场景首选尝试 | ✅ 安全 | ⭐⭐⭐⭐⭐ |
| --trusted-host | 快速临时解决 | ⚠️ 有风险 | ⭐⭐ |
| 企业CA证书 | 公司内网长期使用 | ✅ 安全 | ⭐⭐⭐⭐ |
| 国内镜像源 | 同时提速+可能绕开证书问题 | ✅ 安全 | ⭐⭐⭐⭐⭐ |
| 系统证书更新 | Linux/Windows老系统 | ✅ 安全 | ⭐⭐⭐⭐ |
| 禁用SSL验证 | 仅调试 | ❌ 危险 | ⭐ |
8. 常见问题 FAQ
8.1 conda 环境下的证书问题
conda 安装的 Python 使用自己的证书体系,与系统 Python 独立:
# conda 环境下升级证书 conda install -c conda-forge certifi ca-certificates --force-reinstall # 或者用pip方式(在conda环境内) pip install --upgrade certifi8.2 requests 库单独配置证书路径
如果只是某个 Python 脚本报错,而不是 pip 命令本身:
import requests import certifi # 显式指定使用最新的证书包 response = requests.get("https://example.com", verify=certifi.where())8.3 公司内网使用自签名证书的正确姿势
# 1. 从系统信任列表导出证书(macOS示例) security find-certificate -a -p /Library/Keychains/System.keychain > /tmp/system_certs.pem # 2. 追加到 certifi 证书包 cat /tmp/system_certs.pem >> $(python -c "import certifi; print(certifi.where())")8.4 Windows 上 python.org 安装版本 vs Microsoft Store 版本的差异
Microsoft Store 版本的 Python 通常直接使用 Windows 系统的证书库,很少遇到此问题;而 python.org 官方安装包在某些情况下也可能出现类似 macOS 的证书初始化问题:
# Windows 检查当前使用的证书 python -c "import certifi; print(certifi.where())" # 如果证书文件过旧,直接升级 pip install --upgrade certifi8.5 VPN 软件导致的证书问题
部分 VPN 客户端(尤其是企业级VPN)会对流量进行深度包检测(DPI),插入自己的证书:
# 临时关闭VPN测试是否是VPN导致的问题 # 关闭VPN后重新尝试 pip install pip install requests # 如果关闭VPN后正常,说明需要将VPN的证书添加到信任列表9. 总结
SSL: CERTIFICATE_VERIFY_FAILED的排查顺序:
- macOS 用户:先运行
Install Certificates.command - 所有用户:
pip install --upgrade certifi - 企业网络:配置
--trusted-host或安装企业CA证书 - 顺带提速:切换国内镜像源
- conda用户:单独处理conda环境的证书体系
- VPN用户:排查是否是VPN软件的深度包检测导致
特别提醒:切勿在生产环境或涉及敏感数据传输的场景使用
verify=False或--trusted-host长期绕过证书验证,这会让你的连接暴露在中间人攻击的风险下。