cxfreeze在virtualenv中缺少distutils模块

时间:2013-01-09 21:49:25

标签: python virtualenv distutils cx-freeze

从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中完全安装。

5 个答案:

答案 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库来解决它。我还不知道副作用。一切似乎都运作良好。