使用py2exe

时间:2017-02-15 10:00:11

标签: python-3.x python-requests python-import py2exe

TL; DR

使用requests冻结时,导入py2exe库在Python3项目中失败。 未解冻的项目有效。 问题似乎与requests模块中的相对导入有关。

长描述

我使用Python3创建了一个小项目,并希望将其变成w32的可执行文件。 该项目取决于PySiderequests(2.13.0;实际上这是使用的pyapi-gitlab包的次要依赖项)。 所有依赖项都已通过pip3安装。 Python版本是 3.4.4 (因为PySide不支持任何更高版本的Py3)。 我正在使用py2exe 0.9.2.2

所有内容(例如导入和使用PySide)效果很好,但内部import requests内部失败。

这是一个用于说明问题的极少数示例:

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)

当我从cmdline运行时,我得到:

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>

尼斯。 以下最小setup.py应该将其转换为exe:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe

setup(console=['p2e.py'])

进行实际转换会产生一些“缺失模块”警告:

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>

我经常忽略这些警告,并运行生成的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>

我完全不解。

似乎requests包有一些导入魔法 - 支持包括第三方库(urllib)和包管理器安装的库。 - 支持Py2和Py3(使用six的本地副本)

两者似乎都会产生问题。

我可以修改urllib3问题,修补requests只在相对路径中搜索该包(即使原始代码执行相同操作,仅由try/catch括起来捕获任何ImportError,然后回退到全局导入。)

我不知道如何修复import queue问题。

毕竟,当我在Py3解释器中运行脚本时, 正常工作。

注意

存在类似(可能相同)的问题,但它不包含太多信息:py2exe "requests" module missing

1 个答案:

答案 0 :(得分:2)

看起来urllib3尝试导入失败的queue模块。当失败时,请求无法导入`urllib3。

要强制py2exe包含queue模块,请在调用时使用--includes queue