错误信息
There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
也可能输出为
- Could not fetch URL https://pypi.example.com/simple/requests/: There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
pip 会先打印几行“WARNING: Retrying (Retry(total=…)) after connection broken by 'SSLError(…)'”,然后以“Could not fetch URL <url>: There was a problem confirming the ssl certificate: … - skipping”的形式打印这条错误。URL 和最后的原因各不相同。
pip — index or find-links URL over HTTPS (pip 24.2+ verifies with truststore by default)
含义
pip 无法验证包索引(或某个 find-links URL)的 TLS 证书,于是跳过了该页面,最后通常会报出“Could not find a version that satisfies the requirement”。冒号后面的原因是 OpenSSL 的验证结果。从 pip 24.2 开始,pip 通过 truststore 使用操作系统的证书存储进行验证,因此要么是操作系统的证书存储中缺少该 CA,要么是 pip 被指定使用了另一个证书包。
原因
使用公司证书的私有索引(Artifactory、Nexus、devpi)
常见内部包镜像使用公司 CA 签发的证书,这个 CA 存在于受管理的笔记本电脑上,但不存在于 CI 镜像、容器或新建的虚拟机中。
pypi.org 前面有执行 TLS 检查的代理
常见在公司网络中,代理会对 pypi.org 和 files.pythonhosted.org 重新签名。如果 pip 使用的证书存储中没有该代理的根证书,每次安装都会失败。
pip 被配置为使用 certifi 而不是操作系统的证书存储
偶见使用了 --use-deprecated=legacy-certs、显式设置了指向 certifi 的 cert,或者 pip 运行在 Python 3.9 及更早版本上(这些版本无法使用 truststore),都意味着添加到操作系统证书存储中的根证书不会被使用。
Python 安装自带的旧版 pip
偶见24.2 之前的 pip 始终使用其内置的 certifi 证书包。许多基础镜像和虚拟环境仍然附带这类版本。
修复方法
- 1.
将 CA 安装到操作系统的证书存储
在 Python 3.10+ 上使用 pip 24.2+ 时,系统证书存储(或钥匙串 / Windows 证书存储)中的根证书会被自动信任。如果 pip 版本更旧,请升级 pip。
bash # pip >= 24.2 uses the OS trust store (truststore): add the CA there sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates python3 -m pip --version # upgrade pip itself if it is older than 24.2 - 2.
为 pip 显式指定 CA 证书包
pip 配置中的 global.cert、PIP_CERT 或 --cert 会让 pip 用该文件进行验证。如果 pip 还要访问 pypi.org,就要把公共根证书也包含进去。
bash # A CA bundle for pip only (one of these): python3 -m pip config set global.cert /etc/ssl/private-ca/corp-ca-bundle.pem export PIP_CERT=/etc/ssl/private-ca/corp-ca-bundle.pem python3 -m pip install --cert /etc/ssl/private-ca/corp-ca-bundle.pem requests - 3.
一次性配置私有索引
把 index-url 和 cert 写入 pip.conf(或 pip.ini),让每次 pip 调用——包括构建工具内部的调用——都使用这些设置。
ini # pip.conf (Linux: ~/.config/pip/pip.conf, Windows: %APPDATA%\pip\pip.ini) [global] index-url = https://pypi.example.com/simple/ cert = /etc/ssl/private-ca/corp-ca-bundle.pem - 4.
临时诊断:--trusted-host
--trusted-host 会关闭对该主机的证书验证,并允许 pip 对它使用纯 HTTP。它可以帮助确认诊断,但以这种方式下载的任何内容都可能在传输过程中被替换;切勿把它留在配置中。
bash # Temporary diagnostic only: --trusted-host disables certificate checks for that host python3 -m pip download --no-deps -d /tmp/dl --index-url https://pypi.example.com/simple/ \ --trusted-host pypi.example.com requests