使用distutils / setuptools在安装后执行Python脚本

时间:2021-10-16 01:13:36

I'm trying to add a post-install task to Python distutils as described in How to extend distutils with a simple post install script?. The task is supposed to execute a Python script in the installed lib directory. This script generates additional Python modules the installed package requires.

我正在尝试向Python distutils添加安装后任务,如如何使用简单的安装后脚本扩展distutils中所述。该任务应该在已安装的lib目录中执行Python脚本。此脚本生成安装包所需的其他Python模块。

My first attempt is as follows:

我的第一次尝试如下:

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},
)

This approach works, but as far as I can tell has two deficiencies:

这种方法有效,但据我所知,有两个不足之处:

  1. If the user has used a Python interpreter other than the one picked up from PATH, the post install script will be executed with a different interpreter which might cause a problem.
  2. 如果用户使用的Python解释器不是从PATH中获取的解释器,则安装后脚本将使用不同的解释器执行,这可能会导致问题。

  3. It's not safe against dry-run etc. which I might be able to remedy by wrapping it in a function and calling it with distutils.cmd.Command.execute.
  4. 它对于干运行等是不安全的,我可以通过将其包装在函数中并使用distutils.cmd.Command.execute调用它来解决这个问题。

How could I improve my solution? Is there a recommended way / best practice for doing this? I'd like to avoid pulling in another dependency if possible.

我怎样才能改进我的解决方案?这样做有推荐的方法/最佳实践吗?如果可能的话,我想避免引入另一个依赖。

2 个解决方案

#1


34  

The way to address these deficiences is:

解决这些不足的方法是:

  1. Get the full path to the Python interpreter executing setup.py from sys.executable.
  2. 获取从sys.executable执行setup.py的Python解释器的完整路径。

  3. Classes inheriting from distutils.cmd.Command (such as distutils.command.install.install which we use here) implement the execute method, which executes a given function in a "safe way" i.e. respecting the dry-run flag.

    从distutils.cmd.Command继承的类(例如我们在这里使用的distutils.command.install.install)实现了execute方法,该方法以“安全方式”执行给定函数,即遵循干运行标志。

    Note however that the --dry-run option is currently broken and does not work as intended anyway.

    但请注意, - dr-run选项目前已被破坏,无论如何都无法正常工作。

I ended up with the following solution:

我最终得到了以下解决方案:

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},
)

Note that I use the class name install for my derived class because that is what python setup.py --help-commands will use.

请注意,我为派生类使用类名安装,因为这是python setup.py --help-commands将使用的。

#2


1  

I think the easiest way to perform the post-install, and keep the requirements, is to decorate the call to setup(...):

我认为执行安装后并保持要求的最简单方法是装饰对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=['...
    )
)

This will run setup() when declaring setup. Once done with the requirements installation, it will run the _post_install() function, which will run the inner function _post_actions().

这将在声明设置时运行setup()。完成需求安装后,它将运行_post_install()函数,该函数将运行内部函数_post_actions()。

#1


34  

The way to address these deficiences is:

解决这些不足的方法是:

  1. Get the full path to the Python interpreter executing setup.py from sys.executable.
  2. 获取从sys.executable执行setup.py的Python解释器的完整路径。

  3. Classes inheriting from distutils.cmd.Command (such as distutils.command.install.install which we use here) implement the execute method, which executes a given function in a "safe way" i.e. respecting the dry-run flag.

    从distutils.cmd.Command继承的类(例如我们在这里使用的distutils.command.install.install)实现了execute方法,该方法以“安全方式”执行给定函数,即遵循干运行标志。

    Note however that the --dry-run option is currently broken and does not work as intended anyway.

    但请注意, - dr-run选项目前已被破坏,无论如何都无法正常工作。

I ended up with the following solution:

我最终得到了以下解决方案:

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},
)

Note that I use the class name install for my derived class because that is what python setup.py --help-commands will use.

请注意,我为派生类使用类名安装,因为这是python setup.py --help-commands将使用的。

#2


1  

I think the easiest way to perform the post-install, and keep the requirements, is to decorate the call to setup(...):

我认为执行安装后并保持要求的最简单方法是装饰对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=['...
    )
)

This will run setup() when declaring setup. Once done with the requirements installation, it will run the _post_install() function, which will run the inner function _post_actions().

这将在声明设置时运行setup()。完成需求安装后,它将运行_post_install()函数,该函数将运行内部函数_post_actions()。