10

I'm building an application in python 3.3 which uses the requests library. When I try to get a URL with SSL connection I want to verify it with verify = true. This works perfectly when running my python scripts.

When I freeze the same scripts it crashes. It misses something and I really cant figure out how to integrate it in my frozen application.

I get the following error (which also triggers other errors, but I don't post them here):

Traceback (most recent call last):
File "C:\Python33-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 422, in urlopen
body=body, headers=headers)
File "C:\Python33-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 274, in _make_request
conn.request(method, url, **httplib_request_kw)
File "C:\Python33-32\lib\http\client.py", line 1049, in request
self._send_request(method, url, body, headers)
File "C:\Python33-32\lib\http\client.py", line 1087, in _send_request
self.endheaders(body)
File "C:\Python33-32\lib\http\client.py", line 1045, in endheaders
self._send_output(message_body)
File "C:\Python33-32\lib\http\client.py", line 890, in _send_output
self.send(msg)
File "C:\Python33-32\lib\http\client.py", line 828, in send
self.connect()
File "C:\Python33-32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 105, in connect
ssl_version=self.ssl_version)
File "C:\Python33-32\lib\site-packages\requests\packages\urllib3\util.py", line 281, in ssl_wrap_socket
context.load_verify_locations(ca_certs)
FileNotFoundError: [Errno 2] No such file or directory 

It seems that ca_certs is missing. There is a file called cacert.pem in the requests library, but I don't know if this is the missing file and how to import it since it seems to be not integrated into my final frozen package.

jpeg
  • 2,372
  • 4
  • 18
  • 31
Ecno92
  • 869
  • 11
  • 16
  • Modules that require separate files (like the key file here) tend to have trouble when frozen. You might need to edit requests code. – Thomas K Mar 01 '13 at 13:29
  • Offcourse that's a possibility that will propably work, but it would be nicer if the file is imported into the package from the module folder. Is it also possible to force this specific file to be imported during the freeze process? There are import features available in the setup process, but I don't know how to use them exactly since the official documentation is not very clear about this. – Ecno92 Mar 03 '13 at 22:17

3 Answers3

10

Looking at the requests source, it seems you can pass the path to the cacert.pem file as verify=path, instead of verify=True. So you don't need to modify requests for it to work.

You can pass the path of a file to include in the include-files parameter of the cx_Freeze options (docs). You can find the path from requests, so something like this should work in the setup.py you use to freeze it:

import requests.certs
build_exe_options = {"include_files":[(requests.certs.where(),'cacert.pem')]}

#...
Thomas K
  • 39,200
  • 7
  • 84
  • 86
  • 5
    Thank you very much. This was the solution after a small change. The method you describe is not possible since CX_Freeze will not accept a absolute path like this. The key is to use a tuple where you first give the absolute path in the first half and in the second half the destination path. In this way it worked by setting the verify to True. So like this: "include_files":[(requests.certs.where(),'cacert.pem')] – Ecno92 Mar 05 '13 at 18:09
  • Thanks. I've updated the answer so it's clear for anyone else who comes across this. – Thomas K Mar 06 '13 at 13:05
4

As Thomas K said, you need to include a CA certificates file if you enable verification.

However, I found that at least for me, requests will look for [INSTALL PATH]\library.zip\cacert.pem which will fail.

I solved it by copying the cacert.pem as described

import requests.certs
build_exe_options = {"include_files":[(requests.certs.where(),'cacert.pem')]}

#...

and specified its path directly when performing a request:

requests.get(..., verify = '[INSTALL PATH]\cacert.pem')
Arc
  • 11,143
  • 4
  • 52
  • 75
  • Yes, and the `INSTALL PATH` can be determined by cx_freeze's [suggested method to find data files](https://cx-freeze.readthedocs.org/en/latest/faq.html#using-data-files) – dh762 Mar 02 '16 at 13:44
4

You can also use enviroment variable "REQUESTS_CA_BUNDLE" (as said http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification)

It's much simpler, than correct all your requests:

os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(os.getcwd(), "cacert.pem")
broomrider
  • 614
  • 1
  • 7
  • 16