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