app/notes/20170923-2205.md
Bundling Python Packages With PyInstaller and Requests
pyinstaller-requests
1506204304
I recently tried using [PyInstaller](https://github.com/pyinstaller/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](https://github.com/requests/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](https://github.com/certifi/python-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](http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification))
within your code before using requests:
```python
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
```