35

我正在尝试将安装后任务添加到 Python distutils,如如何使用简单的安装后脚本扩展 distutils?. 该任务应该在已安装的 lib 目录中执行 Python 脚本。此脚本生成已安装包所需的其他 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},
)

这种方法有效,但据我所知有两个缺陷:

  1. 如果用户使用的 Python 解释器不是来自 的解释器PATH,则安装后脚本将使用不同的解释器执行,这可能会导致问题。
  2. 对于空运行等是不安全的,我可以通过将其包装在一个函数中并使用distutils.cmd.Command.execute.

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

4

2 回答 2

38

解决这些缺陷的方法是:

  1. 获取setup.pysys.executable.
  2. 继承自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将要使用的。

于 2013-08-10T08:07:49.080 回答
1

我认为执行安装后并保持要求的最简单方法是装饰对以下的调用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()

于 2018-06-07T12:44:51.247 回答