pythonssl

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


I installed python 3.6 using

brew install python3

and tried to download a file with six.moves.urllib.request.urlretrieve from an https, but it throws the error

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

In the Python installation (from .pkg), the README indicates that one needs to run the Install Certificates.command after the installation to

  1. install certifi
  2. symlink the certification path to certify path

to be able to use certificates.

However, in brew install, this file does not exist and it does not seem to be run.


Solution

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