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

时间:2013-07-23 09:33:05

标签: python install setuptools distutils post-install

我正在尝试按照How to extend distutils with a simple post install script?中的说明向Python 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调用它来解决这个问题。
  3. 我如何改进我的解决方案?这样做有推荐的方法/最佳做法吗?如果可能的话,我想避免引入另一个依赖。

2 个答案:

答案 0 :(得分:34)

解决这些不足的方法是:

  1. setup.py获取执行sys.executable的Python解释器的完整路径。
  2. distutils.cmd.Command继承的类(例如我们在这里使用的distutils.command.install.install)实现了execute方法,该方法以“安全的方式”执行给定的函数,即尊重干涸的旗帜。

    但请注意the --dry-run option is currently broken并且无论如何都无法正常工作。

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

    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将使用的。

答案 1 :(得分: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()