使用Python setuptools安装后脚本

Chr*_*ins 82 python software-distribution setuptools pypi setup.py

是否可以将安装后的Python脚本文件指定为setuptools setup.py文件的一部分,以便用户可以运行该命令:

python setup.py install
Run Code Online (Sandbox Code Playgroud)

在本地项目文件存档,或

pip install <name>
Run Code Online (Sandbox Code Playgroud)

对于PyPI项目,脚本将在标准setuptools安装完成后运行?我希望执行可以在单个Python脚本文件中编码的安装后任务(例如,向用户提供自定义安装后消息,从其他远程源存储库中提取其他数据文件).

几年前我遇到了这个回答这个主题的答案,听起来好像当时的共识是你需要创建一个install子命令.如果仍然如此,那么有人可以提供一个如何执行此操作的示例,以便用户无需输入第二个命令来运行脚本吗?

mer*_*ran 78

这个解决方案更透明:

您将对setup.py进行一些添加,并且不需要额外的文件.

您还需要考虑两种不同的后期安装; 一个用于开发/可编辑模式,另一个用于安装模式.

将包含安装后脚本的这两个类添加到setup.py:

from setuptools import setup
from setuptools.command.develop import develop
from setuptools.command.install import install


class PostDevelopCommand(develop):
    """Post-installation for development mode."""
    def run(self):
        # PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTION
        develop.run(self)

class PostInstallCommand(install):
    """Post-installation for installation mode."""
    def run(self):
        # PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTION
        install.run(self)
Run Code Online (Sandbox Code Playgroud)

并在setup.py中插入cmdclass函数的参数:setup()

setup(
    ...

    cmdclass={
        'develop': PostDevelopCommand,
        'install': PostInstallCommand,
    },

    ...
)
Run Code Online (Sandbox Code Playgroud)

您甚至可以在安装后调用shell命令,如下所示:

from setuptools import setup
from setuptools.command.develop import develop
from setuptools.command.install import install
from subprocess import check_call


class PostDevelopCommand(develop):
    """Post-installation for development mode."""
    def run(self):
        check_call("apt-get install this-package".split())
        develop.run(self)

class PostInstallCommand(install):
    """Post-installation for installation mode."""
    def run(self):
        check_call("apt-get install this-package".split())
        install.run(self)


setup(
    ...
Run Code Online (Sandbox Code Playgroud)

PS在setuptools上没有任何预先安装的入口点.如果您想知道为什么没有,请阅读此讨论.

  • 这取决于你:如果你在父*上首先调用`run`,那么你的命令是安装后的,否则就是预装.我已经更新了答案以反映这一点. (6认同)
  • 似乎只适用于“setup.py install”,而不是“pip install”包时。 (4认同)
  • 对于pip3来说,这对我不起作用。发布包时运行安装脚本,但安装时不运行。 (3认同)
  • @Raf 有没有适用于“setup.py install”和“pip install”的解决方案? (3认同)
  • 使用此解决方案似乎忽略了“install_requires”依赖项 (2认同)

Apa*_*ala 11

当安装后脚本要求已经安装了软件包依赖项时,这是唯一对我有用的策略:

import atexit
from setuptools.command.install import install


def _post_install():
    print('POST INSTALL')


class new_install(install):
    def __init__(self, *args, **kwargs):
        super(new_install, self).__init__(*args, **kwargs)
        atexit.register(_post_install)


setuptools.setup(
    cmdclass={'install': new_install},
Run Code Online (Sandbox Code Playgroud)

  • 那么其他答案对我不起作用:要么不执行安装后脚本,要么不再处理依赖项.到目前为止,我将坚持使用`atexit`而不是**重新定义`install.run()`(这就是为什么不再处理依赖的原因).另外,为了知道安装目录,我把`_post_install()`作为`new_install`的方法,让我可以访问`self.install_purelib`和`self.install_platlib`(不知道哪个一个要使用,但``self.install_lib`是错的,很奇怪). (3认同)
  • 此处的方法似乎都不适用于轮子。轮子不运行setup.py,因此消息仅在构建时显示,而在安装软件包时不显示。 (3认同)
  • 我也遇到了依赖问题,而 atexit 对我有用 (2认同)
  • 感谢您提供这个答案。它对我有用(@mertyildiran 提供的答案也是如此)。我发现的一件事是,仅当我在详细模式下运行 pip install 时,才会显示“print”语句的输出,例如:“pip3 install -v -e”。 (2认同)

Zul*_*ulu 6

一个解决方案可能是包含一个post_setup.pyin setup.py目录.post_setup.py将包含一个执行安装后的功能,setup.py只会在适当的时候导入并启动它.

setup.py:

from distutils.core import setup
from distutils.command.install_data import install_data

try:
    from post_setup import main as post_install
except ImportError:
    post_install = lambda: None

class my_install(install_data):
    def run(self):
        install_data.run(self)
        post_install()

if __name__ == '__main__':
    setup(
        ...
        cmdclass={'install_data': my_install},
        ...
    )
Run Code Online (Sandbox Code Playgroud)

post_setup.py:

def main():
    """Do here your post-install"""
    pass

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

通过setup.py从其目录启动的共同想法,您将能够导入post_setup.py其他将启动空函数.

post_setup.py,该if __name__ == '__main__':语句允许您从命令行手动启动安装后.

  • 在我的例子中,重写``run()``导致不安装包依赖. (3认同)