cxfreeze отсутствует модуль distutils внутри virtualenv
При запуске двоичного файла cxfreeze из проекта python3.2 я получаю следующую ошибку во время выполнения:
/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 setup.py
как:
options = {"build_exe": {"packages" : ["distutils"]} },
Ни один из подходов не сработал. Кажется вероятным, что я каким-то образом сломал virtualenv [поскольку distutils кажется основополагающим, а предупреждение о местонахождении distutils], повторяя с чистым virtualenv, повторил проблему.
Может быть стоит отметить, что я установил cx-freeze, запустив $VIRTUAL_ENV/build/cx-freeze/setup.py install
поскольку он не устанавливается чисто в пипсах.
5 ответов
Обобщая мои комментарии:
Копия distutils
в virtualenv делает некоторые странные вещи, которые сбивают с толку cx_Freeze. Простой обходной путь - заморозить виртуальную среду, чтобы она использовала системную копию distutils.
В Ubuntu Python 2 и 3 счастливо сосуществуют: просто используйте python3
сделать что-нибудь с Python 3. Например, чтобы установить cx_Freeze под Python 3: python3 setup.py install
,
Найден другой обходной путь, который позволяет вам все еще использовать 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)],
)
Благодарю Бруно Оливейру за ответ на github
Полный ответ в гисте: https://gist.github.com/nicoddemus/ca0acd93a20acbc42d1d
Я нашел обходной путь о 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
пакет из исходного интерпретатора в каталог, содержащий ваш замороженный исполняемый файл.
Хакки и некрасиво, но это работает. Я хотел бы услышать идеи для улучшения хотя.
Это было давно, но я столкнулся с той же проблемой. Я смог решить эту проблему, скопировав пакет distutils из локальной библиотеки Python в библиотеку virtualenv. Я еще не знаю о побочных эффектах. Кажется, все работает хорошо.
Одна из проблем заключается в том, что distutils/__init__.py в вашем venv пытается выполнить неявный относительный импорт (импорт dist вместо правильного import из distutils import dist), так что это будет первое, что нужно исправить. Как был создан venv? Откуда берется distutils/__init__.py?