6

从 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

distutils相应地,在 cxfreeze 输出的缺失模块部分中有几个条目:

? 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 中来强制将 distutils 作为模块包含在内setup.py

options = {"build_exe": {"packages" : ["distutils"]} },

两种方法都不起作用。似乎我以某种方式破坏了 virtualenv [因为 distutils 似乎很重要,并且关于 distutils 位置的警告],重复使用干净的 virtualenv 复制了问题。

值得注意的是,我通过运行安装了 cx-freeze,$VIRTUAL_ENV/build/cx-freeze/setup.py install因为它没有在 pip 中干净地安装。

4

5 回答 5

8

找到了另一种解决方法,它使您在冻结时仍然可以使用 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

于 2015-10-30T14:17:38.690 回答
2

总结我的评论:

virtualenv 中的副本distutils正在做一些使 cx_Freeze 感到困惑的奇怪事情。简单的解决方法是在 virtualenv 之外冻结,以便它使用 distutils 的系统副本。

在 Ubuntu 上,Python 2 和 3 愉快地共存:只需使用python3Python 3 做任何事情。例如在 Python 3 下安装 cx_Freeze: python3 setup.py install

于 2013-01-12T13:31:18.660 回答
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包从原始解释器复制到包含冻结的可执行文件的目录。

黑客和丑陋,但它的工作原理。不过,我很想听听改进的想法。

于 2015-09-25T02:32:05.723 回答
0

一个问题是 venv 中的 distutils/__init__.py 尝试进行隐式相对导入(导入 dist 而不是正确的 from distutils import dist),因此这是首先要解决的问题。venv 是如何创建的?distutils/__init__.py 来自哪里?

于 2013-01-11T00:51:53.900 回答
0

已经有一段时间了,但我遇到了同样的问题。我能够通过将 distutils 包从本地 Python 库复制到 virtualenv 库来解决它。我还不知道副作用。一切似乎都运作良好。

于 2015-09-01T12:17:55.063 回答