使用 distutils / setuptools 执行 Python 脚本安装后
Posted
技术标签:
【中文标题】使用 distutils / setuptools 执行 Python 脚本安装后【英文标题】:Execute a Python script post install using distutils / setuptools 【发布时间】:2013-07-22 07:18:01 【问题描述】:我正在尝试向 Python distutils 添加一个安装后任务,如How to extend distutils with a simple post install script? 中所述。该任务应该在已安装的 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,
)
这种方法有效,但据我所知有两个不足:
-
如果用户使用的 Python 解释器不是从
PATH
获取的解释器,则安装后脚本将使用 不同的解释器执行,这可能会导致问题。
它对空运行等是不安全的,我可以通过将其包装在一个函数中并使用 distutils.cmd.Command.execute
调用它来进行补救。
如何改进我的解决方案?有推荐的方法/最佳实践吗?如果可能的话,我想避免引入另一个依赖项。
【问题讨论】:
对于那些想要同时使用python setup.py install
,以及pip install
的人,请参阅:***.com/questions/21915469/…
【参考方案1】:
解决这些不足的方法是:
-
从
sys.executable
获取执行setup.py
的Python解释器的完整路径。
从distutils.cmd.Command
继承的类(例如我们在此处使用的distutils.command.install.install
)实现execute
方法,该方法以“安全方式”执行给定函数,即尊重试运行标志。
但是请注意,the --dry-run
option is currently broken 无论如何都不能按预期工作。
我最终得到了以下解决方案:
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
将使用的。
【讨论】:
谢谢,这真的很有帮助,我还需要关注 (***.com/questions/15853058/…) 以避免我的 pip 安装出错。我将所有内容放在一篇博文 (diffbrent.ghost.io/…) 中。如果我错过了什么,请告诉我。 @brent.payne 很高兴听到它有帮助!请注意我对为什么使用install
作为类名的评论。
它可以工作,但我无法使用pip install -e name
执行自定义安装。 ps,刚刚找到this link,见BONUS部分。
看起来非常好,使用setuptools
而不是distutils
后安装部分仍然可以正常运行,但setuptools
处理依赖关系的能力似乎丢失了(它们只是被忽略了)。
@Paolo 的链接已移至:blog.niteo.co/setuptools-run-custom-code-in-setup-py【参考方案2】:
我认为执行安装后并保持要求的最简单方法是装饰对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()
。
【讨论】:
此代码似乎无法按预期工作...它将直接运行_post_action ...以上是关于使用 distutils / setuptools 执行 Python 脚本安装后的主要内容,如果未能解决你的问题,请参考以下文章
Python setuptools/distutils 使用 Makefile 自定义构建 `extra` 包
如何将安装后脚本添加到 easy_install / setuptools / distutils?
python3 安装 pip3 出现问题??distutils.core 不存在
YOLOV7:AttributeError: module ‘distutils‘ has no attribute ‘version‘ 的解决方案