Notes

Bundling Python Packages with PyInstaller and Requests

September 23, 2017

I recently tried using PyInstaller to bundle python applications as a single binary executable. Pyinstaller was relatively easy to use and its documentation is pretty good. However, I ran into a bit of trouble bundling the python requests package because of problems with requests looking for a trusted certificates file, usually emitting an error like OSError: Could not find a suitable TLS CA certificate bundle, invalid path: .... In a typical installation, the certifi package includes a set of trusted CA certificates but when PyInstaller bundles the requests and ceritifi packages, certifi can’t provide a file path for requests to use.

The way to fix this is to set the REQUESTS_CA_BUNDLE variable (documentation) within your code before using requests:

import pkgutil
import requests
import tempfile

# Read the cert data
cert_data = pkgutil.get_data('certifi', 'cacert.pem')

# Write the cert data to a temporary file
handle = tempfile.NamedTemporaryFile(delete=False)
handle.write(cert_data)
handle.flush()

# Set the temporary file name to an environment variable for the requests package
os.environ['REQUESTS_CA_BUNDLE'] = handle.name

# Make requests using the requests package
requests.get('https://www.albertyw.com/')

# Clean up the temp file