2

我创建了一个使用 pythonnet 的 python 脚本。该脚本位于一个名为main.py. 当我从命令行运行脚本时(只需main.py在 Windows 命令提示符下键入),导入的 pythonnet 模块clr工作正常。但是当我尝试构建一个 exe 时,我收到一条错误消息:No module named clr.

为了找出造成这种情况的原因,我已经验证了使用 py2exe 构建可执行文件(在我的例子中是一个简单的 Tkinter 应用程序)是可行的。我只安装了 Python 3.4 并验证了where python指向C:\Python34\python.exe.

该错误发生在可执行构建时,似乎是通过包含在 my forclr部分中触发的。完整的回溯如下:{"includes":["sip","clr"]}}setup.pypy2exe

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'

我还阅读/尝试了这些:

https://docs.python.org/2/distutils/setupscript.html
https://pythonhosted.org/setuptools/setuptools.html
http://sourceforge.net/p/py2exe/mailman/message/6937658

引导我移动clr.pydPython.Runtime.dll进入不同的位置main.py,包括 , 的位置C:\Python34\Lib\site-packages(它们最初所在的位置)和C:\Python34\Lib\site-packages\py2exe

这些都没有奏效,我不知道下一步该尝试什么。我可以看到由于某种原因py2exe找不到任何一个clr.pydPython.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构建,但显然无法正常运行。

4

1 回答 1

4

###安装说明

作为参考,我执行了py2exeusing的标准安装pip install py2exe。这将py2exe放入Lib\site-packages您的 python 安装中。接下来,我通过从 Christoph Gohlke 的非官方 Windows 二进制文件页面pythonnet下载安装,然后使用. 这将放入您的python 安装。 这个问题和答案有更多信息。.whlpip install path\to\pythonnet-2.0.0<version_numbers>.whlclr.pydPython.Runtime.dllLib\site-packages

###问题

这是一个相当奇怪的行为py2exe,很难调试。我认为这纯粹是该工具中的一个错误。此外,错误消息没有帮助。

问题是clr该工具通过其hooks.py文件专门排除了该模块。目前尚不清楚为什么。您可以在此处查看执行此排除的行

###解决方案

clr解决方法是从py2exe 安装中的windows_excludes变量文件中删除该单词。hooks.py假设一切都在其标准位置 - 这意味着删除hooks.py位于C:\Python34\Lib\site-packages\py2exe. 你还需要确保它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
)

编辑:对于任何感兴趣的人-我在聊天对话中更详细地描述了我是如何隔离和发现这个错误的。

于 2015-05-19T21:30:05.587 回答