Как использовать distutils для создания исполняемого файла .zip? - PullRequest
6 голосов
/ 01 июня 2011

В 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 в верхней части архива.

Ответы [ 2 ]

4 голосов
/ 01 июня 2011

Обновлено : Поскольку setup.cfg является глобальным, он влияет на настройку 'install-lib' для всех команд, что не является желаемым.К сожалению, нет способа (насколько мне известно) передать опции подкоманде через командную строку, например, если вы укажете bdist --install-lib=/, она выдаст ошибку вместо передачи ее подкомандам.

Комунастроить install-lib для подкоманды install only при запуске 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 голос
/ 07 января 2015

Можно также сделать исполняемый файл 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 становится возможным.

Сейчас я не могу сказать, как пропатчить команду distutils sdist для автоматического внедрения этого __main__.py в .zip, но это определенно реально.

...