Pyinstaller error ImportError: No module named 'requests.packages.chardet.sys

Pyinstaller error ImportError: No module named 'requests.packages.chardet.sys

我似乎找不到这个问题的根本原因。不知道是pyinstaller问题,还是pip问题,还是requests模块问题,还是别的什么问题,最终排除不了。

我在 python 中编写了一个脚本,当我们必须部署一个新单元时,它可以为我们的企业网络正确配置一个新的硬件 sonicwall。它在内存中配置一个正确的 .exp 文件,使用默认凭证登录到 sonicwall 设备,通过多部分数据表单导入文件,重新启动 sonicwall,然后再次登录并正确更改共享密钥。出于安全原因,我不能在此处 post 代码,但我可以用一个更简单的示例来解释问题。以前,代码是使用 urllib 和 urllib2 来处理 http 请求,但是当我不得不重写脚本以包含 csrfTokens 时,我发现了 requests 模块。

长话短说,脚本在被 python 解释器调用时效果惊人。但是,当尝试使用 pyinstaller 编译它时,由于我已切换到请求而不是 urllibs,所以出现了一系列错误。

更多背景:

Windows 7 - Python2.7.9
pip 6.0.8 from C:\Python27\lib\site-packages\pip-6.0.8-py2.7.egg (python 2.7)
pip freeze output:
pyinstaller==2.1.1.dev0
pywin32==219
requests==2.5.3

举个例子,我会给你一些炸毁的代码,一个简单的请求 google。

#!/usr/bin/python
import requests 
r = requests.get('https://google.com') 
print(r.text)

当我从 python 调用文件时,上面的代码适用于一个简单的请求,但是当我编译它时,我得到这个:

(编辑粘贴输出时遇到问题,这里是 pastebin) pastebin

它创建了一个 windows 可执行文件,但是当我尝试 运行 它时出现以下错误:

注意 我确实安装了 ms c++ 2008 可再发行组件以帮助清除 msvcr90.dll,但我仍然遇到上述 requests.packages.chardet.sys 错误。

我已经尝试了所有我能想到的方法,安装 chardet,安装 chardet2,安装 cchardet,强制使用早期版本的 pyinstaller 和增量请求。废弃 pip 并手动安装 pyinstaler 和 requests。我对尝试的事情束手无策,我不太明白这里的错误。 requests.packages.chardet 存在于系统中。我的 windows 路径中也有 C:\Python27,因为我可以从任何目录调用 python。

如果您需要更多信息,请告诉我。我尝试尽可能彻底地了解错误和我安装的内容,但如果需要,我可以提供更多。

ALSO 这个问题似乎只在我导入请求时尝试编译时才会发生。创建测试脚本、beautifulsoup、urllib/2 等都会编译一个有效的 windows exe,运行 正确。

我还没有解决方案,但这是由 requests 模块(版本 2.5.2 和 2.5.3)的最新更改引起的。

目前您可以使用 2.5.1 版,直到 PyInstaller 有合适的钩子来解决这个问题。

我无法真正解释这个问题,但看起来 PyInstaller 导入挂钩与 requests (VendorAlias) 的一些最新添加之间存在某种冲突。

我认为问题出在Setuptools版本上,所以请尝试使用旧版本并再次测试。就我而言,它有效!

>> pip uninstall setuptools
>> pip install setuptools==12.0.5

我想这个问题与位置参数的解释有关

正如 m1keil 所说,问题出在 PyInstaller 导入挂钩和请求的新 load_module 功能之间,在 requests.packages.__init__.py 源文件中实现。

调试此文件,您可以看到请求包的任何导入都通过 load_module 函数传递。这包括 python 标准包。这是错误的原因。

我的解决方法是编辑 2.5.3 版的 requests.packages.__init__.py(在 virtualenv 文件夹内)并在 load_module 函数的最开头添加这段代码:

    print "Requested name = ", name #Comment this line when it works
    direct_loaded_packages = ('sys', 'errno','logging','warnings'
            ,'socket','os','re','time','hashlib','base64'
            ,'time','collections','datetime','io', 'argparse'
            ,'codecs', 'Queue', 'zlib', 'ssl', 'operator'
            ,'types','platform','struct', 'StringIO','httplib'
            ,'simplejson','cookielib','urllib','urlparse'
            ,'urllib2','Cookie','http','binascii','certifi'
            ,'uuid','json','threading','dummy_thread','email'
            ,'email.utils','operator','mimetypes')    


    new_name = ''
    #Package with three directory deep 
    if '.'.join(name.split('.')[3:]) in direct_loaded_packages:
        new_name = '.'.join(name.split('.')[3:])
    #Package with four directory deep
    elif '.'.join(name.split('.')[4:]) in direct_loaded_packages:
        new_name = '.'.join(name.split('.')[4:])
    #Package with five directory deep
    elif '.'.join(name.split('.')[5:]) in direct_loaded_packages:
        new_name = '.'.join(name.split('.')[5:])

    if new_name != '':
        module = __import__(new_name)
        return module 

通过 test&error 和 grepping,我已经构建了必须直接加载的包列表,而无需通过 load_module 函数。

不是很优雅,但很管用。我已经测试了一个更优雅的解决方案,但我没有成功。

好消息,此问题已在最新版本 requests

中修复
pip install requests --upgrade

简单。

我在 运行 我的 python 可执行文件(例如 "no module named requests"、"no module named cv2"、...)时遇到了一些错误,我通过升级 setuptools 解决了这个问题:

pip install setuptools --upgrade