Подтвердить что ты не робот

Выполните установку post python script с помощью distutils/setuptools

Я пытаюсь добавить задачу после установки в Python distutils, как описано в Как расширить distutils с помощью простой пост-установки script?. Предполагается, что задача должна выполнить Python script в установленном каталоге lib. Этот script генерирует дополнительные модули Python, которые требует установленный пакет.

Моя первая попытка следующая:

from distutils.core import setup
from distutils.command.install import install

class post_install(install):
    def run(self):
        install.run(self)
        from subprocess import call
        call(['python', 'scriptname.py'],
             cwd=self.install_lib + 'packagename')

setup(
 ...
 cmdclass={'install': post_install},
)

Этот подход работает, но, насколько я могу судить, имеет два недостатка:

  • Если пользователь использовал интерпретатор Python, отличный от того, который был выбран из PATH, post install script будет выполняться с другим интерпретатором, который может вызвать проблему.
  • Он не защищен от сухого пробега и т.д., который я мог бы исправить, обернув его функцией и называя его distutils.cmd.Command.execute.

Как я могу улучшить свое решение? Есть ли рекомендуемый способ/наилучшая практика для этого? Я хотел бы избежать по возможности затягивания другой зависимости.

4b9b3361

Ответ 1

Способ устранения этих недостатков:

  • Получить полный путь к интерпретатору Python, выполняющему setup.py из sys.executable.
  • Классы, наследующие от distutils.cmd.Command (например, distutils.command.install.install, которые мы здесь используем) реализуем метод execute, который выполняет заданную функцию "безопасным способом", то есть соблюдает флаг сухого пробега.

    Обратите внимание, что параметр --dry-run в настоящее время отключен и не работает должным образом.

У меня получилось следующее решение:

import os, sys
from distutils.core import setup
from distutils.command.install import install as _install


def _post_install(dir):
    from subprocess import call
    call([sys.executable, 'scriptname.py'],
         cwd=os.path.join(dir, 'packagename'))


class install(_install):
    def run(self):
        _install.run(self)
        self.execute(_post_install, (self.install_lib,),
                     msg="Running post install task")


setup(
    ...
    cmdclass={'install': install},
)

Обратите внимание, что я использую имя класса install для моего производного класса, потому что это то, что будет использовать python setup.py --help-commands.

Ответ 2

Я думаю, что самый простой способ выполнить пост-установку и сохранить требования - украсить вызов setup(...):

from setup tools import setup


def _post_install(setup):
    def _post_actions():
        do_things()
    _post_actions()
    return setup

setup = _post_install(
    setup(
        name='NAME',
        install_requires=['...
    )
)

Это приведет к запуску setup() при объявлении setup. После выполнения установки требований будет запущена _post_install(), которая будет запускать внутреннюю функцию _post_actions().