我似乎无法找到这个的根本原因。我不知道它是pyinstaller,pip问题,请求模块还是别的东西,因为没有什么可以最终消除。
我在python中编写了一个脚本,当我们必须部署一个新单元时,它为我们的企业网络正确配置了一个新的硬件sonicwall。它在内存中配置正确的.exp文件,使用默认凭据登录到sonicwall设备,通过多部分数据表单导入文件,重新启动sonicwall,然后再次登录并正确更改共享密钥。出于安全原因,我不能在这里发布代码,但我可以用一个更简单的例子来解释这个问题。以前,代码使用urllib和urllib2来处理http请求,但是当我不得不重新编写脚本以包含csrfTokens时,我发现了请求模块。
长话短说,这个脚本在python解释器调用时效果很好。但是,当尝试使用pyinstaller编译它时,我得到了一系列错误,因为我已切换到请求而不是urllib。
更多背景:
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
作为一个例子,我会给你一些炸弹的代码,一个简单的谷歌请求。
#!/usr/bin/python
import requests
r = requests.get('https://google.com')
print(r.text)
当我从python调用文件时,上面的代码适用于一个简单的请求,但是当我编译它时,我得到这个:
(编辑粘贴输出有问题,这里是pastebin)
引擎收录
它创建一个Windows可执行文件,但是当我尝试运行它时出现以下错误:
注意 我确实安装了ms c ++ 2008 redistributable以帮助清理msvcr90.dll,但我仍然得到上面的requests.packages.chardet.sys错误。
我已经尝试了我能想到的一切,安装chardet,安装chardet2,安装cchardet,强制pyinstaller的早期版本和递增请求。废弃pip并手动安装pyinstaler和请求。我的智慧结束了尝试的事情,我不太明白这里的错误。 requests.packages.chardet存在于系统中。我在Windows PATH中也有C:\ Python27,因为我可以从任何目录调用python。
如果您需要更多信息,请告诉我。我试图尽可能彻底地解决错误和我已安装的错误,但如果需要我可以提供更多错误。
也 当我在导入请求时尝试编译时,这个问题似乎只会发生。创建测试脚本,beautifulsoup,urllib / 2等都编译一个正常运行的有效Windows exe。
我还没有解决方案,但这是由最新的变化引起的 requests
模块(版本2.5.2和2.5.3)。
现在你可以使用版本2.5.1,直到PyInstaller有合适的钩子来解决这个问题。
我无法解释这个问题,但看起来之间存在某种冲突 PyInstaller
导入钩子和一些最新的补充 requests
(VendorAlias)。
好消息,这已在最新版本中修复 requests
pip install requests --upgrade
简单。
正如m1keil所说,问题出在PyInstaller导入钩子和新的load_module请求功能之间,在 requests.packages.__init__.py
源文件。
调试此文件可以看到请求包的任何导入都通过load_module函数传递。这包括python标准包。这就是错误的原因。
我的解决方法包括编辑 requests.packages.__init__.py
(在virtualenv文件夹中)版本2.5.3并在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
通过测试和错误以及grepping我已经构建了必须直接加载而不通过load_module函数的包列表。
不优雅,但它的工作原理。我测试了一个更优雅的解决方案,但我还没有成功。
我认为问题是出于问题 setuptools的 版本,所以尝试使用旧版本并再次测试它。就我而言,它有效!
>> pip uninstall setuptools
>> pip install setuptools==12.0.5
我猜这个麻烦与位置论证的解释有关