#python #distutils #python-2.6
#питон #искажения #python-2.6 #python #distutils
Вопрос:
Python 2.6 и выше имеет возможность прямого выполнения zip-файла, если zip-файл содержит __main__.py
файл в верхней части zip-архива. Я хочу использовать эту функцию для предоставления предварительных версий разрабатываемого мной инструмента, который не потребует от пользователей установки чего-либо, кроме копирования zip-файла на свой диск. Существует ли стандартный способ создания такого zip-файла? Я ищу решение, которое работает с python 2.6 и python 2.7.
В идеале я хотел бы использовать distutils, поскольку он у меня уже работает, когда я хочу выполнить обычную установку. Существует ли канонический способ использования (или расширения) distutils для создания такого zip-файла?
distutils предоставляет sdist
команду, которая создает исходный дистрибутив, который почти правильный, но создает структуру, которая немного слишком глубока.
Например, мое дерево исходных текстов выглядит следующим образом:
my_package/
- setup.py
- src/
- __main__.py
- module1/
- module2/
- module3/
Когда я это делаю python setup.py sdist
, в итоге получается zip-файл со следующей структурой:
my_package-0.1.zip
- my_package-0.1/
- README.txt
- PKG_INFO
- src/
- __main__.py
- module1/
- module2/
- module3/
Это не исполняемый файл, потому что __main__.py
он не находится в верхней части дистрибутива. Фактически, то, что я хочу, — это дистрибутив src, который не включает src
, а только файлы под src
. Это, или именно то, что sdist
дает мне, но с добавлением __main__.py
в верхней части архива.
Ответ №1:
Обновлено: поскольку setup.cfg
это глобальное, это влияет на настройку ‘install-lib’ для всех команд, что не является желательным. К сожалению, насколько мне известно, нет способа передать параметры подкоманде через командную строку, например, если вы укажете bdist --install-lib=/
, это вызовет ошибку вместо передачи ее подкомандам.
Чтобы настроить install-lib
для install
подкоманды только при bdist
запуске, вы можете подклассировать bdist_dumb
команду и задать путь вручную после того, как install
подкоманда будет создана / повторно инициализирована:
setup.py
from distutils.core import setup
from distutils.command.bdist_dumb import bdist_dumb
class custom_bdist_dumb(bdist_dumb):
def reinitialize_command(self, name, **kw):
cmd = bdist_dumb.reinitialize_command(self, name, **kw)
if name == 'install':
cmd.install_lib = '/'
return cmd
if __name__ == '__main__':
setup(
# our custom class override
cmdclass = {'bdist_dumb': custom_bdist_dumb},
name='my_package',
py_modules = ['__main__'],
packages = ['module1', 'module2'],
package_dir = {'': 'src'}
)
Выполняется:
% python setup.py bdist --format=zip
% unzip -l dist/my_package-0.0.0.linux-x86_64.zip
Archive: dist/my_package-0.0.0.linux-x86_64.zip
Length Date Time Name
--------- ---------- ----- ----
184 2011-05-31 20:34 my_package-0.0.0.egg-info
30 2011-05-31 20:34 __main__.py
128 2011-05-31 20:34 __main__.pyc
107 2011-05-31 20:34 module1/__init__.pyc
0 2011-05-31 20:27 module1/__init__.py
107 2011-05-31 20:34 module2/__init__.pyc
0 2011-05-31 20:27 module2/__init__.py
--------- -------
556 7 files
% python dist/my_package-0.0.0.linux-x86_64.zip
my_package working.
Комментарии:
1. Однако я обнаружил, что выполнение этого означает, что выполнение «setup.py установка «завершается с ошибкой, поскольку она пытается записать в «/». Мне нужна возможность как создать zip-файл, так и установить обычным способом.
2. @Bryan Я обновил ответ, чтобы исправить это, и вы можете удалить
setup.cfg
изменения. Надеюсь, решение сработает для вас.3. Черт возьми, когда я запускал это в Windows в оболочке cygwin (не уверен, имеет ли это значение …) Я получил ‘ValueError: path’ / ‘не может быть абсолютным’. Изменение
cmd.install_lib = '/'
наcmd.install_lib = '\'
устранило эту проблему.
Ответ №2:
Можно также создать sdist
исполняемый файл, поместив следующий __main__.py
файл в корень вашего .zip:
import os
import sys
# add package .zip to python lookup path
__dir__ = os.path.dirname(__file__)
path = os.path.join(__dir__, 'my_package-0.1', 'src')
sys.path.insert(0, path)
import module1
module1.main()
Это добавляет вложенный каталог исходного кода из архива в, sys.path
так что импорт из module1
становится возможным.
Я не могу сказать прямо сейчас, как исправить sdist
команду distutils, чтобы автоматически вводить это __main__.py
в .zip
, но это определенно реально.