TL;DR
Importing the requests
library fails within a Python3 project when frozen with py2exe
.
The unfrozen project works.
The problem seems to be related to relative imports within the requests
module.
long description
I've created a little project using Python3, and would like to turn it into an executable for w32.
The project depends on PySide
and requests
(2.13.0; actually this is a secondary dependency of the used pyapi-gitlab
package).
All dependencies have been installed via pip3
.
Python version is 3.4.4 (since PySide doesn't support any later versions of Py3).
I'm using py2exe 0.9.2.2
.
Everything (e.g. importing and using PySide
) works great, but the import requests
deep inside fails.
Here's a somewhat minimal example to illustrate the problem:
import logging
logging.basicConfig()
log = logging.getLogger()
import sys
print("Python: %s" % (sys.version,))
try:
import requests
except ImportError:
log.fatal("failed to import 'requests'", exc_info=True)
When I run this from the cmdline, I get:
E:\p2e> python p2e.py
Python: 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (Intel)]
E:\p2e>
Nice.
The following minimal setup.py
is supposed to turn this into an exe:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe
setup(console=['p2e.py'])
Doing the actual conversion gives a number of "missing modules" warnings:
E:\p2e> python setup.py py2exe
running py2exe
24 missing Modules
------------------
? Cookie imported from requests.compat
? OpenSSL imported from requests.packages.urllib3.contrib.pyopenssl
? Queue imported from requests.packages.urllib3.connectionpool
? _abcoll imported from requests.packages.urllib3.packages.ordered_dict
? backports imported from requests.packages.urllib3.packages.ssl_match_hostname
? certifi imported from requests.certs
? chardet imported from requests.packages
? cookielib imported from requests.compat
? cryptography imported from requests.packages.urllib3.contrib.pyopenssl
? idna imported from requests.models, requests.packages.urllib3.contrib.pyopenssl
? netbios imported from uuid
? readline imported from cmd, code, pdb
? simplejson imported from requests.compat
? six imported from requests.packages.urllib3.contrib.pyopenssl
? socks imported from requests.packages.urllib3.contrib.socks
? urllib.getproxies imported from requests.compat
? urllib.proxy_bypass imported from requests.compat
? urllib.quote imported from requests.compat
? urllib.quote_plus imported from requests.compat
? urllib.unquote imported from requests.compat
? urllib.unquote_plus imported from requests.compat
? urllib.urlencode imported from requests.compat
? urllib3 imported from requests.packages
? win32wnet imported from uuid
Building 'dist\p2e.exe'.
Building shared code archive 'dist\library.zip'.
Copy c:\windows\system32\python34.dll to dist
Copy C:\Python34\DLLs\_ssl.pyd to dist\_ssl.pyd
Copy C:\Python34\DLLs\_lzma.pyd to dist\_lzma.pyd
Copy C:\Python34\DLLs\select.pyd to dist\select.pyd
Copy C:\Python34\DLLs\_hashlib.pyd to dist\_hashlib.pyd
Copy C:\Python34\DLLs\_ctypes.pyd to dist\_ctypes.pyd
Copy C:\Python34\DLLs\_bz2.pyd to dist\_bz2.pyd
Copy C:\Python34\DLLs\_socket.pyd to dist\_socket.pyd
Copy C:\Python34\DLLs\pyexpat.pyd to dist\pyexpat.pyd
Copy C:\Python34\DLLs\unicodedata.pyd to dist\unicodedata.pyd
E:\p2e>
I routinely ignore these warnings, and run the generated exe:
E:\p2e> dist\p2e.exe
CRITICAL:root:failed to import 'requests'
Traceback (most recent call last):
File "c:\Python34\lib\site-packages\requests\packages\__init__.py", line 27, in <module>
from . import urllib3
File "c:\Python34\lib\site-packages\requests\packages\urllib3\__init__.py", line 8, in <module>
from .connectionpool import (
File "c:\Python34\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 28, in <module>
from .packages.six.moves import queue
File "c:\Python34\lib\site-packages\requests\packages\urllib3\packages\six.py", line 92, in __get__
result = self._resolve()
File "c:\Python34\lib\site-packages\requests\packages\urllib3\packages\six.py", line 115, in _resolve
return _import_module(self.mod)
File "c:\Python34\lib\site-packages\requests\packages\urllib3\packages\six.py", line 82, in _import_module
__import__(name)
ImportError: No module named 'queue'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "p2e.py", line 9, in <module>
File "c:\Python34\lib\site-packages\requests\__init__.py", line 63, in <module>
from . import utils
File "c:\Python34\lib\site-packages\requests\utils.py", line 24, in <module>
from ._internal_utils import to_native_string
File "c:\Python34\lib\site-packages\requests\_internal_utils.py", line 11, in <module>
from .compat import is_py2, builtin_str, str
File "c:\Python34\lib\site-packages\requests\compat.py", line 11, in <module>
from .packages import chardet
File "c:\Python34\lib\site-packages\requests\packages\__init__.py", line 29, in <module>
import urllib3
ImportError: No module named 'urllib3'
Python: 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (Intel)]
E:\p2e>
I'm totally puzzled.
It seems that the requests
package does some import magic to
- support both included 3rd-party libs (urllib
) and libs installed by package managers.
- support both Py2 and Py3 (using a local copy of six
)
Both seem to create problems.
I can amend the urllib3
problem, by patching requests
to only search for that package in relative paths (even though the original code does the same, only enclosed by a try/catch
that catches any ImportError
and then falls back to import globally.)
I have no idea how to fix the import queue
problem.
And after all, it is working properly when I run the script in the Py3 interpreter.
NOTE
There's a similar (maybe the same) issue, but it doesn't include that much information: py2exe "requests" module missing