从python3.2项目运行cxfreeze二进制文件时,我收到以下运行时错误:
/project/dist/project/distutils/__init__.py:13: UserWarning: The virtualenv distutils package at %s appears to be in the same location as the system distutils?
Traceback (most recent call last):
File "/home/chrish/.virtualenvs/project/lib/python3.2/distutils/__init__.py", line 19, in <module>
import dist
ImportError: No module named dist
相应地,cxfreeze输出的缺失模块部分中有几个distutils
条目:
? dist imported from distutils
? distutils.ccompiler imported from numpy.distutils.ccompiler
? distutils.cmd imported from setuptools.dist
? distutils.command.build_ext imported from distutils
? distutils.core imported from numpy.distutils.core
...
我已经尝试强制将distutils作为模块包含在内,通过在我的主python文件中导入它并将其添加到cxfreeze setup.py
中:
options = {"build_exe": {"packages" : ["distutils"]} },
两种方法都不奏效。似乎我已经以某种方式破坏了virtualenv [因为distutils似乎是基本的并且关于distutils位置的警告],重复一个干净的virtualenv复制了这个问题。
值得注意的是,我通过运行$VIRTUAL_ENV/build/cx-freeze/setup.py install
安装了cx-freeze,因为它没有在pip中完全安装。
答案 0 :(得分:6)
找到另一种解决方法,使您在冻结时仍然可以使用virtualenv。
解决方法是排除distutils并手动从原始解释器(而不是virtualenv)添加包。
# contents of setup.py
from cx_Freeze import setup, Executable
import distutils
import opcode
import os
# opcode is not a virtualenv module, so we can use it to find the stdlib; this is the same
# trick used by distutils itself it installs itself into the virtualenv
distutils_path = os.path.join(os.path.dirname(opcode.__file__), 'distutils')
build_exe_options = {'include_files': [(distutils_path, 'distutils')], "excludes": ["distutils"]}
setup(
name="foo",
version="0.1",
description="My app",
options={"build_exe": build_exe_options},
executables=[Executable("foo_main.py", base=None)],
)
感谢Bruno Oliveira对github的回答 完整答案:https://gist.github.com/nicoddemus/ca0acd93a20acbc42d1d
答案 1 :(得分:2)
总结我的评论:
virtualenv中distutils
的副本正在做一些让cx_Freeze混淆的奇怪事情。简单的解决方法是在virtualenv之外冻结,以便它使用distutils的系统副本。
在Ubuntu上,Python 2和3很高兴共存:只需使用python3
对Python 3做任何事情。在Python 3下安装cx_Freeze:python3 setup.py install
。
答案 2 :(得分:2)
我在distutils
内冻结virtualenv
问题后找到了一个可能对其他人有帮助的解决方法。
首先确保从您的版本中排除distutils
:
build_exe_options = {'excludes': ['distutils']}
其次在setup.py
文件中声明此功能:
def copy_distutils_to_build_dir(build_dir):
# the code below was obtained from the distutils.py file created by
# virtualenv
import opcode
dirname = os.path.dirname
distutils_path = os.path.join(os.path.dirname(opcode.__file__), 'distutils')
target_dir = os.path.join(build_dir, 'distutils')
if os.path.isdir(target_dir):
shutil.rmtree(target_dir)
shutil.copytree(distutils_path, target_dir)
最后,在setup()
中调用setup.py
后调用函数:
setup(...)
copy_distutils_to_build_dir(join('build', 'exe.win32-3.4'))
这会将整个distutils
包从原始解释器复制到包含冻结可执行文件的目录。
答案 3 :(得分:0)
一个问题是你的venv中的distutils / __ init__.py尝试进行隐式相对导入(import dist而不是distutils import dist中的正确),所以这将是第一个要修复的东西。 venv是如何创建的? distutils / __ init__.py来自哪里?
答案 4 :(得分:0)
现在已经有一段时间,但我遇到了同样的问题。我能够通过将distutils包从本地Python库复制到virtualenv库来解决它。我还不知道副作用。一切似乎都运作良好。