certifi/python-certifi

"__file__" variable cannot be used when running with frozen program

hahuunguyen opened this issue · 11 comments

After freezing my Python application, I got an error while getting a certificate.

File "/usr/lib/python3.5/importlib/_bootstrap.py", line 816, in exec_module
    exec(code, module.__dict__)
File "/usr/local/lib/python3.5/dist-packages/requests/utils.py", line 39, in <module>
    DEFAULT_CA_BUNDLE_PATH = certs.where()
File "/usr/local/lib/python3.5/dist-packages/certifi/core.py", line 22, in where
    f = os.path.split(__file__)[0]
NameError: name '__file__' is not defined

The reason is the "file" variable in cannot be used in frozen program.
https://stackoverflow.com/questions/21937695/python-cx-freeze-name-file-is-not-defined

Could it be better to handle the frozen program case:

try:
    approot = os.path.dirname(os.path.abspath(__file__))
except NameError:  
    import sys
    approot = os.path.dirname(os.path.abspath(sys.argv[0]))
    return os.path.join(approot, 'cacert.pem')

It's not clear to me why we need to write custom code to handle application freezing. This fundamentally seems like a problem with cxfreeze, especially as I'm not sure the problem exists anywhere else.

This was also an issue if it's run from a whl. This happend to me when I tried to replace the ubuntu supplied requests whl in venv>/share/python-wheel: I had to replace requests and some other files. In the end I needed certifi as well and simply dropping it into the dir as a *.whl didn't work because the path ended up as /home/js/project/.venv/share/python-wheels/certifi-2017.7.27.1-py2.py3-none-any.whl/certifi/cacert.pem

The workaround was to install certifi directly after the venv creation via pip (=installed not in a whl) and then replace the requests, chardet, idna, and urllib3 whl in <venv>/share/python-wheel/.

alex commented

Wheels are not intended to be run from, wheels are a distribution format that are installed from.

How are you installing certifi such that it tries to be imported from a whl?

I use ubuntu and ubuntu uses a 'un-vendored' pip and requests. All the wheels are in /usr/share/python-wheels. Pip then imports them from there (https://github.com/pypa/pip/blob/master/src/pip/_vendor/__init__.py#L61).

Currently the version of requests there is old and so does not require certifi, but has probelms with retries (see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=870701), so I tried to replace it as mentioned in the bug report. But this needed certifi then and resulted in the bug above when I added the whl to that directory.

evanj commented

I ran into this because I am attempting to use certifi packaged in a standalone zip. For example, packaged with pex or par. I would be happy to submit a test and a patch that changes where() to detect if it is inside a zip, and if so to extract it to a temporary file, which I think would solve this issue.

However, this is admittedly a rare use case, so I would also accept "sorry we won't do this" as an answer.

I'm running into this same issue trying to use the boto3 and requests libraries in an AWS Glue Spark environment, which runs the user's python library code directly from a zip without extracting first. This may apply to other Spark environments too, I'm not positive.

It looks like requests recently merged a change to handle this in their library, but it seems a shame to make each library author implement that code -- my thought was the same as @evanj , perhaps we could use similar code to what requests added directly in certifi and fix it for all users?

I’d accept a patch that detects the zip case and runs the extraction.

evanj commented

PR #82 fixes the issue in my case; Not sure about the others

__file__ is not mandated to exist. Custom Python module importers are allowed to not define it if modules aren't backed by files. So strictly speaking certifi and every other Python application relying on the existence of __file__ are buggy. More information including how to work around the problem is available at indygreg/PyOxidizer#69.

#120 was reverted but the functionality was re-added in 3fc8fec.

@Lukasa Can you please make another release?

Done.