Mac OSX python出现ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)错误

114

在Python中,许多操作需要通过https访问。包括pip install命令,或只是使用http.client.HTTPSConnection,或任何内部使用这些东西的模块或应用程序。

如果从https://python.org下载官方Python pkg安装程序进行安装,则会使用openssl的内部版本,并且不包含根证书。任何使用SSL连接的内容都会导致此错误:

ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)

我该如何安装根证书以消除上述错误?


你应该重新安装包含Python的Xcode命令行工具。 - Victor Kushnerov
17个回答

245
当你运行Python安装程序时,他们会向你显示这些信息。它也记录在/Applications/Python 3.6/ReadMe.rtf中,但很容易被忽视。
只需浏览到Applications/Python 3.6,然后双击Install Certificates.command Python错误跟踪器中有一个问题。 http://bugs.python.org/issue29480 更新:这个问题在错误跟踪器中标记为已解决,最新评论中包含以下文本:

...对于3.7.0b2,我尝试通过两种方式使事情更加明显。一,安装程序包现在将尝试打开包含“Install Certificates.command”的/Application/Python 3.7文件夹的Finder窗口。二,与其仅在安装完成时显示通用的“安装完成”消息不同,现在有一条量身定制的消息,敦促用户单击“Install Certificates.command”图标......


2
如果没有root权限,是否有解决方案?谢谢。 - tommy.carstensen
4
我运行了Install Certificates.command文件,但是如果在我的代码中使用https URL(读取内容),错误仍然存在(在Py36中)。如果我使用相同的URL字符串去掉"s"(例如http),我的代码可以工作。不幸的是,我需要https来访问某些URL。有任何建议吗?(我也运行了"pip3 install --upgrade certifi",因为我需要同时使用Py27和Py36) - ultrageek
2
这个不起作用,所有错误都仍然存在,就像@ultrageek所提到的那样。此外,请列出实际命令,而不是捆绑在特定版本Python中的别名。-1。 - hpm
20
我在应用程序文件夹中没有Python。 - flppv
5
@gma992 我通过Homebrew和pyenv安装了Python。在存储我的Python版本的目录中,我没有看到安装证书的命令。 - Khalil Hijazi
显示剩余10条评论

58

我有Python3.9,只需将7更改为9即可,谢谢! - Jesus Walker
谢谢,在Python 3.6中也可以工作,或者只需运行python3.6 -m pip install -U certifi对我来说就可以。 - Rainy Chan

57

解决所有 Python 版本问题的酷方法,无需在 macOS 上检查您的版本

bash /Applications/Python*/Install\ Certificates.command

这个命令等同于:

...
bash /Applications/Python\ 2.7/Install\ Certificates.command
bash /Applications/Python\ 3.6/Install\ Certificates.command
bash /Applications/Python\ 3.7/Install\ Certificates.command
...

它帮助了我,希望它也能帮助你


% python3 get-pip.py --> 警告:连接中断后重试(Retry(total=0, connect=None, read=None, redirect=None, status=None)):/simple/pip/ 无法获取URL https://pypi.org/simple/pip/:确认ssl证书时出现问题:HTTPSConnectionPool(host='pypi.org', port=443):超过了最大重试次数,URL为:/simple/pip/(由于SSLError(SSLCertVerificationError(1,'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:992)'))引起) - Ashish Karpe
[SSL: CERTIFICATE_VERIFY_FAILED]证书验证失败:证书链中存在自签名证书(_ssl.c:992)'))) - 跳过 错误:找不到满足pip要求的版本(来自版本:none) - Ashish Karpe
bash /Applications/Python*/Install\ Certificates.command-- pip install --upgrade certifi/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11: No module named pipTraceback (most recent call last): File "<stdin>", line 44, in <module> File "<stdin>", line 24, in main File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/subprocess.py", line 413, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: 命令' '的返回值为:1。 - Ashish Karpe
'/Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11', '-E', '-s', '-m', 'pip', 'install', '--upgrade', 'certifi' 返回了非零退出状态 1。 - Ashish Karpe

40
如果pip解决不了这个问题
pip3 install --upgrade certifi

如果找不到 "Install Certificates.command",请尝试以下脚本:

#!/usr/bin/env python3
# install_certifi.py
#
# sample script to install or update a set of default Root Certificates
# for the ssl module.  Uses the certificates provided by the certifi package:
#       https://pypi.python.org/pypi/certifi

import os
import os.path
import ssl
import stat
import subprocess
import sys

STAT_0o775 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
             | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
             | stat.S_IROTH |                stat.S_IXOTH )


def main():
    openssl_dir, openssl_cafile = os.path.split(
        ssl.get_default_verify_paths().openssl_cafile)

    # +++> if already done  <----
    #print(" -- pip install --upgrade certifi")
    #subprocess.check_call([sys.executable,
    #    "-E", "-s", "-m", "pip", "install", "--upgrade", "certifi"])

    import certifi
    # change working directory to the default SSL directory
    os.chdir(openssl_dir)
    relpath_to_certifi_cafile = os.path.relpath(certifi.where())
    print(" -- removing any existing file or link")
    try:
        os.remove(openssl_cafile)
    except FileNotFoundError:
        pass
    print(" -- creating symlink to certifi certificate bundle")
    os.symlink(relpath_to_certifi_cafile, openssl_cafile)
    print(" -- setting permissions")
    os.chmod(openssl_cafile, STAT_0o775)
    print(" -- update complete")

if __name__ == '__main__':
    main()

2
谢谢。对我有用。可能是许多情况下唯一可行的解决方案。 - Mercado
花了几个小时在这上面,尝试了许多其他的SO解决方案...这是唯一有效的一个。我使用Homebrew安装的Python 3.8。 - Justin
经过多次尝试不同的解决方案,这最终解决了问题。谢谢。 - gma992
不是所有英雄都穿斗篷,伙计,你刚刚救了我的命!谢谢 (^_^) - madprogramer
在Ubuntu上工作了!经过多次尝试,这是唯一有效的解决方案!你真是太棒了! - Ronnieeeone
显示剩余7条评论

9

如果您使用的是MacOS,请进入“应用程序”>>“python3.8”>>并双击“Install Certificates.command”。

我这样做可以解决问题。


7

在我的情况下,无论是在macOS Catalina 中使用系统安装的 python3,还是通过 brew 安装的 python3,都没有解决方案有效。

如果有人遇到像我一样的问题,想要快速解决,
请重新下载并安装 python3,使用 https://www.python.org/downloads/

在安装完成时,安装程序会显示一个提示,请运行 Install Certificates.command 文件。
(其他安装方式中没有此文件,也不会出现该解决方案与文件源代码的工作情况)

重新启动终端,您可以输入 where python3,然后查看 /Library/Frameworks/Python.framework/Versions/3.8/bin/python3。使用这个二进制文件,问题应该不会再出现。

注意:也许可以让系统自带的 python3 生效,但在我的情况下非常困难,所以我选择了这种方式。


1
这让我在尝试让我的bitbar python3插件工作时找到了正确的解决方案。我发现我有几个python3安装,使用which python3命令更改脚本shebang为#!/usr/local/bin/python3修复了SSL错误。谢谢! - Michael

3

当我尝试通过Keras加载数据运行Python时,我遇到了同样的问题。我的错误信息如下:

Exception: URL fetch failure on AWS_URL: None -- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)

我通过升级证书解决了我的问题:

pip install --upgrade certifi

你好!是 pip install --upgrade certificate 对吧?我修改了你的帖子,但不确定这是一个拼写错误还是我不知道的模块。 - creyD
还是这个模块吗?如果不是,请随意更正! - creyD
3
这并不是拼写错误,只是一个模块名称。 - Ratha Pech

2

确认你没有在虚拟环境中。

我尝试了上述方法,但没有成功,后来才意识到我的安装失败是因为我在虚拟环境中。


如何在虚拟环境中使其正常工作? - Valentino Pereira
@ValentinoPereira,请检查虚拟环境中的Python版本,并尝试使用 "/Applications/Python {version}/Install Certificates.command" 进行更新。 - StackEdd

1
一种经济的方法是,如果您仍然安装了Python3.5,则可以直接使用它。
推送到PyPI: python3.5 setup.py register -r pypitest python3.5 setup.py sdist upload -r pypitest pipping似乎可以很好地与3.6配合使用...

0
对我来说,那是一个请求错误的说明。我使用了https调用代替了http调用。改成http解决了这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接