brew installation of Python 3.6.1: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

It seems that, for some reason, Brew has not run the Install Certificates.command that comes in the Python3 bundle for Mac. The solution to this issue is to run the following script (copied from Install Certificates.command) after brew install 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)

    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()

My solution for Mac OS X:

1) Upgrade to Python 3.6.5 using the native app Python installer downloaded from the official Python language website https://www.python.org/downloads/

I've found that this installer is taking care of updating the links and symlinks for the new Python a lot better than homebrew.

2) Install a new certificate using "./Install Certificates.command" which is in the refreshed Python 3.6 directory

cd "/Applications/Python 3.6/" sudo "./Install Certificates.command"


  • find out default cafile:
python -c 'import ssl; print(ssl.get_default_verify_paths().openssl_cafile)'

/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/etc/ssl/cert.pem

sudo mkdir -p /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/etc/ssl/certs
  • find out ca file of certifi
python -c 'import certifi; print(certifi.where())'

'/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'

  • copy to
sudo cp /usr/local/lib/python3.7/site-packages/certifi/cacert.pem
/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/etc/ssl/certs/cert.pem

Tags:

Python

Ssl