尝试使用 pythonnet 从脚本构建 exe 时,py2exe 失败并显示 "No module named 'clr'"
py2exe fails with "No module named 'clr'" when trying to build exe from script using pythonnet
我创建了一个使用 pythonnet 的 python 脚本。该脚本位于名为 main.py
的文件中。当我从命令行 运行 脚本(只需在 Windows 命令提示符下键入 main.py
时),导入的 pythonnet 模块 clr
工作正常。但是当我尝试构建一个 exe 时,我收到一条错误消息:No module named clr
.
为了查明原因,我已经验证使用 py2exe 构建可执行文件(在我的例子中是一个简单的 Tkinter 应用程序)是可行的。我只安装了 Python 3.4 并验证 where python
指向 C:\Python34\python.exe
.
该错误发生在可执行构建时,似乎是由于在我的 setup.py
的 py2exe
部分 {"includes":["sip","clr"]}}
中包含 clr
触发的。完整的追溯如下:
Traceback (most recent call last):
File "setup.py", line 32, in <module>
windows = [{'script': "main.py"}],
File "C:\Python34\lib\distutils\core.py", line 148, in setup
dist.run_commands()
File "C:\Python34\lib\distutils\dist.py", line 917, in run_commands
self.run_command(cmd)
File "C:\Python34\lib\distutils\dist.py", line 936, in run_command
cmd_obj.run()
File "C:\Python34\lib\site-packages\py2exe\distutils_buildexe.py", line 188, i
n run
self._run()
File "C:\Python34\lib\site-packages\py2exe\distutils_buildexe.py", line 267, i
n _run
builder.analyze()
File "C:\Python34\lib\site-packages\py2exe\runtime.py", line 164, in analyze
mf.import_hook(modname)
File "C:\Python34\lib\site-packages\py2exe\mf3.py", line 120, in import_hook
module = self._gcd_import(name)
File "C:\Python34\lib\site-packages\py2exe\mf3.py", line 273, in _gcd_import
raise ImportError('No module named {!r}'.format(name), name=name)
ImportError: No module named 'clr'
我也read/tried这些:
https://docs.python.org/2/distutils/setupscript.html
https://pythonhosted.org/setuptools/setuptools.html
http://sourceforge.net/p/py2exe/mailman/message/6937658
引导我将 clr.pyd
和 Python.Runtime.dll
移动到不同的位置,包括 main.py
、C:\Python34\Lib\site-packages
(它们原来所在的位置)和 C:\Python34\Lib\site-packages\py2exe
的位置
None 这些已经奏效,我不知道下一步该尝试什么。我可以看到由于某种原因 py2exe
找不到 clr.pyd
或 Python.Runtime.dll
或两者,但不明白为什么。有人有什么想法吗?
代码详情
我的 main.py
脚本如下所示:
import clr
clr.AddReference("name.xxxx")
from name.xxxx import aaa
from clr import System
# All my functioning code, that I've verified works when run from the command line
这是我的 setup.py
文件包含的内容(我留下了一些注释以便您可以看到我尝试过的内容):
from distutils.core import setup
import py2exe, sys, os
mydata_files = []
for files in os.listdir('C:\d\Project\TOOLS\data_acquisition\trunk\DLL'):
f1 = 'C:\d\Project\TOOLS\data_acquisition\trunk\DLL\' + files
if os.path.isfile(f1): # skip directories
f2 = '.', [f1]
mydata_files.append(f2)
setup(
data_files=mydata_files,
# options = {"py2exe" : {"includes" : "module1,module2,module3"}}
options = {"py2exe": {"includes":["sip", "clr"]}},
# options = {'py2exe': {'bundle_files': 1 , 'compressed': True,"includes":["sip"]}},
#python setup.py py2exe
#CLR.dll and PythonRuntime.dll
# options = {'py2exe': {'bundle_files': 1, "skip_archive":1 ,"includes":["sip"]}},
windows = [{'script': "main.py"}],
# data_files=mydata_files,
# zipfile = None
)
如果我将行 options = {"py2exe": {"includes":["sip", "clr"]}},
更改为 options = {"py2exe": {"includes":["sip"]}},
,则 .exe
会构建,但显然无法正常运行。
###安装说明
作为参考,我使用 pip install py2exe
执行了 py2exe
的标准安装。这会将 py2exe
放入您的 python 安装的 Lib\site-packages
中。接下来,我通过下载 .whl
from Christoph Gohlke's unofficial Windows binaries page, then using pip install path\to\pythonnet-2.0.0<version_numbers>.whl
. This puts clr.pyd
and Python.Runtime.dll
into Lib\site-packages
for your python install. This question and answers 安装了 pythonnet
有更多信息。
###问题
这是 py2exe
的一个相当奇怪的行为,很难调试。我认为这纯粹是该工具中的错误。此外,错误消息没有帮助。
问题是模块 clr
通过其 hooks.py
file. It is not clear why. You can see the line that does this exclusion here.
被该工具明确排除
###解决方案
解决方法是从 py2exe 安装中的 windows_excludes
变量 hooks.py
文件中删除单词 clr
。假设一切都在其标准位置 - 这意味着删除位于 C:\Python34\Lib\site-packages\py2exe
的文件 hooks.py
中的第 23 行。您还需要确保 Python.Runtime.dll
以某种方式与您的 .exe
打包 - 我通过将它添加到数据文件来测试它。这是我测试和工作的示例 - 我使用了一个非常简单的 main.py
来说明导入并确保程序确实在运行。我让你的 setup.py 尽可能接近你的版本,注释掉不适合我的系统的行
要实际制作 .exe
- 使用以下内容(如果 python 是 Python 3 安装的别名,则可能不需要 python.exe 的路径)
C:\python34\python.exe setup.py py2exe
###main.py
import clr
# I import clr, but don't use it as this is not my
# expertise. The fact it imports without error means
# I'm pretty sure it will work
with open('out.txt','a') as f:
for i in range(30):
f.write(str(i))
###setup.py
from distutils.core import setup
import py2exe, sys, os
mydata_files = []
# I had to comment these out as they did not apply to my test environment
# for files in os.listdir('C:\d\Project\TOOLS\data_acquisition\trunk\DLL'):
# f1 = 'C:\d\Project\TOOLS\data_acquisition\trunk\DLL' + files
# if os.path.isfile(f1): # skip directories
# f2 = 'dll', [f1]
# mydata_files.append(f2)
# It's essential that the Python.Runtime.dll is packaged with main.exe
# This is how I've done it
mydata_files.append(('.',['C:\Python34\Lib\site-packages\Python.Runtime.dll']))
setup(
data_files=mydata_files,
# I've left all your commented lines in - they weren't necessary for my test
# options = {"py2exe" : {"includes" : "module1,module2,module3"}}
# I haven't included sip as I don't have it installed, but I think it will work
options = {"py2exe": {"includes":["clr"]}},
# options = {'py2exe': {'bundle_files': 1 , 'compressed': True,"includes":["sip"]}},
#python setup.py py2exe
#CLR.dll and PythonRuntime.dll
# options = {'py2exe': {'bundle_files': 1, "skip_archive":1 ,"includes":["sip"]}},
windows = [{'script': "main.py"}],
# data_files=mydata_files,
# zipfile = None
)
编辑: 对于任何感兴趣的人 - 我在 a chat conversation 中更详细地描述了我是如何隔离和发现这个错误的。
我创建了一个使用 pythonnet 的 python 脚本。该脚本位于名为 main.py
的文件中。当我从命令行 运行 脚本(只需在 Windows 命令提示符下键入 main.py
时),导入的 pythonnet 模块 clr
工作正常。但是当我尝试构建一个 exe 时,我收到一条错误消息:No module named clr
.
为了查明原因,我已经验证使用 py2exe 构建可执行文件(在我的例子中是一个简单的 Tkinter 应用程序)是可行的。我只安装了 Python 3.4 并验证 where python
指向 C:\Python34\python.exe
.
该错误发生在可执行构建时,似乎是由于在我的 setup.py
的 py2exe
部分 {"includes":["sip","clr"]}}
中包含 clr
触发的。完整的追溯如下:
Traceback (most recent call last):
File "setup.py", line 32, in <module>
windows = [{'script': "main.py"}],
File "C:\Python34\lib\distutils\core.py", line 148, in setup
dist.run_commands()
File "C:\Python34\lib\distutils\dist.py", line 917, in run_commands
self.run_command(cmd)
File "C:\Python34\lib\distutils\dist.py", line 936, in run_command
cmd_obj.run()
File "C:\Python34\lib\site-packages\py2exe\distutils_buildexe.py", line 188, i
n run
self._run()
File "C:\Python34\lib\site-packages\py2exe\distutils_buildexe.py", line 267, i
n _run
builder.analyze()
File "C:\Python34\lib\site-packages\py2exe\runtime.py", line 164, in analyze
mf.import_hook(modname)
File "C:\Python34\lib\site-packages\py2exe\mf3.py", line 120, in import_hook
module = self._gcd_import(name)
File "C:\Python34\lib\site-packages\py2exe\mf3.py", line 273, in _gcd_import
raise ImportError('No module named {!r}'.format(name), name=name)
ImportError: No module named 'clr'
我也read/tried这些:
https://docs.python.org/2/distutils/setupscript.html
https://pythonhosted.org/setuptools/setuptools.html
http://sourceforge.net/p/py2exe/mailman/message/6937658
引导我将 clr.pyd
和 Python.Runtime.dll
移动到不同的位置,包括 main.py
、C:\Python34\Lib\site-packages
(它们原来所在的位置)和 C:\Python34\Lib\site-packages\py2exe
的位置
None 这些已经奏效,我不知道下一步该尝试什么。我可以看到由于某种原因 py2exe
找不到 clr.pyd
或 Python.Runtime.dll
或两者,但不明白为什么。有人有什么想法吗?
代码详情
我的 main.py
脚本如下所示:
import clr
clr.AddReference("name.xxxx")
from name.xxxx import aaa
from clr import System
# All my functioning code, that I've verified works when run from the command line
这是我的 setup.py
文件包含的内容(我留下了一些注释以便您可以看到我尝试过的内容):
from distutils.core import setup
import py2exe, sys, os
mydata_files = []
for files in os.listdir('C:\d\Project\TOOLS\data_acquisition\trunk\DLL'):
f1 = 'C:\d\Project\TOOLS\data_acquisition\trunk\DLL\' + files
if os.path.isfile(f1): # skip directories
f2 = '.', [f1]
mydata_files.append(f2)
setup(
data_files=mydata_files,
# options = {"py2exe" : {"includes" : "module1,module2,module3"}}
options = {"py2exe": {"includes":["sip", "clr"]}},
# options = {'py2exe': {'bundle_files': 1 , 'compressed': True,"includes":["sip"]}},
#python setup.py py2exe
#CLR.dll and PythonRuntime.dll
# options = {'py2exe': {'bundle_files': 1, "skip_archive":1 ,"includes":["sip"]}},
windows = [{'script': "main.py"}],
# data_files=mydata_files,
# zipfile = None
)
如果我将行 options = {"py2exe": {"includes":["sip", "clr"]}},
更改为 options = {"py2exe": {"includes":["sip"]}},
,则 .exe
会构建,但显然无法正常运行。
###安装说明
作为参考,我使用 pip install py2exe
执行了 py2exe
的标准安装。这会将 py2exe
放入您的 python 安装的 Lib\site-packages
中。接下来,我通过下载 .whl
from Christoph Gohlke's unofficial Windows binaries page, then using pip install path\to\pythonnet-2.0.0<version_numbers>.whl
. This puts clr.pyd
and Python.Runtime.dll
into Lib\site-packages
for your python install. This question and answers 安装了 pythonnet
有更多信息。
###问题
这是 py2exe
的一个相当奇怪的行为,很难调试。我认为这纯粹是该工具中的错误。此外,错误消息没有帮助。
问题是模块 clr
通过其 hooks.py
file. It is not clear why. You can see the line that does this exclusion here.
###解决方案
解决方法是从 py2exe 安装中的 windows_excludes
变量 hooks.py
文件中删除单词 clr
。假设一切都在其标准位置 - 这意味着删除位于 C:\Python34\Lib\site-packages\py2exe
的文件 hooks.py
中的第 23 行。您还需要确保 Python.Runtime.dll
以某种方式与您的 .exe
打包 - 我通过将它添加到数据文件来测试它。这是我测试和工作的示例 - 我使用了一个非常简单的 main.py
来说明导入并确保程序确实在运行。我让你的 setup.py 尽可能接近你的版本,注释掉不适合我的系统的行
要实际制作 .exe
- 使用以下内容(如果 python 是 Python 3 安装的别名,则可能不需要 python.exe 的路径)
C:\python34\python.exe setup.py py2exe
###main.py
import clr
# I import clr, but don't use it as this is not my
# expertise. The fact it imports without error means
# I'm pretty sure it will work
with open('out.txt','a') as f:
for i in range(30):
f.write(str(i))
###setup.py
from distutils.core import setup
import py2exe, sys, os
mydata_files = []
# I had to comment these out as they did not apply to my test environment
# for files in os.listdir('C:\d\Project\TOOLS\data_acquisition\trunk\DLL'):
# f1 = 'C:\d\Project\TOOLS\data_acquisition\trunk\DLL' + files
# if os.path.isfile(f1): # skip directories
# f2 = 'dll', [f1]
# mydata_files.append(f2)
# It's essential that the Python.Runtime.dll is packaged with main.exe
# This is how I've done it
mydata_files.append(('.',['C:\Python34\Lib\site-packages\Python.Runtime.dll']))
setup(
data_files=mydata_files,
# I've left all your commented lines in - they weren't necessary for my test
# options = {"py2exe" : {"includes" : "module1,module2,module3"}}
# I haven't included sip as I don't have it installed, but I think it will work
options = {"py2exe": {"includes":["clr"]}},
# options = {'py2exe': {'bundle_files': 1 , 'compressed': True,"includes":["sip"]}},
#python setup.py py2exe
#CLR.dll and PythonRuntime.dll
# options = {'py2exe': {'bundle_files': 1, "skip_archive":1 ,"includes":["sip"]}},
windows = [{'script': "main.py"}],
# data_files=mydata_files,
# zipfile = None
)
编辑: 对于任何感兴趣的人 - 我在 a chat conversation 中更详细地描述了我是如何隔离和发现这个错误的。