Выполните скрипт установки Python после установки, используя distutils / setuptools
Я пытаюсь добавить задачу после установки в дистрибутив Python, как описано в разделе Как расширить distutils с помощью простого скрипта после установки?, Задача должна выполнить скрипт Python в установленной директории lib. Этот скрипт генерирует дополнительные модули 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
сценарий после установки будет выполнен с другим интерпретатором, который может вызвать проблему. - Это небезопасно против пробного запуска и т. Д., Который я мог бы исправить, обернув его в функцию и вызвав его
distutils.cmd.Command.execute
,
Как я могу улучшить свое решение? Есть ли рекомендуемый способ / лучшие практики для этого? Я хотел бы, если это возможно, избежать другой зависимости.
2 ответа
Способ устранения этих недостатков:
- Получить полный путь к выполнению интерпретатора 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
буду использовать.
Я думаю, что самый простой способ выполнить постинсталляцию и сохранить требования - это украсить вызов 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()
,