跳到主要内容
ecdsa.com
Python urllib.requestPython cryptography 库

错误信息

<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

也可能输出为

  • urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

尖括号内的文本是底层的 ssl 错误,内容各不相同(“self-signed certificate in certificate chain”、“certificate has expired”等)。Python 以源代码位置和“>”结束这段文本,例如“(_ssl.c:1082)>”。

Python urllib.request — urllib.error.URLError wrapping ssl.SSLCertVerificationError

含义

urllib.request.urlopen() 会把任何连接问题包装成 URLError,因此 TLS 失败显示在“<urlopen error …>”中。如果所有公共网站(包括 www.python.org)都出现这个错误,说明这个 Python 进程根本没有可用的 CA 证书:典型情况是 macOS 上的 python.org 安装程序,其自带的 OpenSSL 在运行“Install Certificates.command”之前不会读取钥匙串。

原因

修复方法

  1. 1.

    macOS:运行 Install Certificates.command

    为每个 python.org Python 版本从访达(Finder)或终端运行它,然后确认默认的 CA 文件路径存在。

    bash
    # macOS, python.org installer (one script per installed version)
    "/Applications/Python 3.14/Install Certificates.command"
    python3 -c "import ssl; print(ssl.get_default_verify_paths().openssl_cafile)"
  2. 2.

    传入基于 certifi 构建的上下文

    对于必须在任何环境中都能运行的脚本,显式地基于 certifi.where() 构建 SSL 上下文;并及时更新 certifi,使其根证书保持最新。

    python
    # Explicit, portable: use certifi's Mozilla bundle for this request
    # pip install certifi
    import certifi, ssl, urllib.request
    
    ctx = ssl.create_default_context(cafile=certifi.where())
    urllib.request.urlopen("https://www.python.org/", context=ctx)
  3. 3.

    或者使用操作系统的证书存储

    truststore.inject_into_ssl() 让 urllib、http.client 以及基于 ssl 构建的库通过操作系统进行验证,IT 部门部署的公司根证书也包含在内。

    python
    # Or verify with the operating system's store (macOS Keychain, Windows, Linux bundle)
    # pip install truststore==0.10.5
    import truststore
    truststore.inject_into_ssl()
  4. 4.

    检查环境变量是否覆盖了默认设置

    如果 SSL_CERT_FILE 和 SSL_CERT_DIR 指向的文件不包含所需的根证书,就取消设置它们。

    bash
    env | grep -E '^SSL_CERT_(FILE|DIR)='
    python3 -c "import ssl; print(ssl.get_default_verify_paths())"

相关错误

浏览完整的签名错误库