是否可以将安装后的Python脚本文件指定为setuptools setup.py文件的一部分,以便用户可以运行该命令:
python setup.py install
在本地项目文件存档上,或
pip install <name>
对于PyPI项目,脚本将在标准setuptools安装完成后运行?我希望执行可以在单个Python脚本文件中编码的安装后任务(例如,向用户提供自定义安装后消息,从其他远程源存储库中提取其他数据文件)。
我遇到了解决该主题的this SO answer from several years ago,听起来好像当时的共识是你需要创建一个install子命令。如果仍然如此,是否有人可以提供如何执行此操作的示例,以便用户无需输入第二个命令来运行脚本?
答案 0 :(得分:61)
此解决方案更透明:
您将对 setup.py 添加一些内容,而无需额外的文件。
另外,您需要考虑两种不同的后期安装;一个用于开发/可编辑模式,另一个用于安装模式。
将包含您的安装后脚本的这两个类添加到 setup.py :
if (dot) *dot = '.';
并在{strong> 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)
函数插入cmdclass
参数:
setup()
您甚至可以在安装后调用shell命令,如下所示:
setup(
...
cmdclass={
'develop': PostDevelopCommand,
'install': PostInstallCommand,
},
...
)
P.S。 setuptools上没有任何预安装入口点。如果您想知道为什么没有,请阅读this discussion。
答案 1 :(得分: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},
答案 2 :(得分:6)
解决方案可能是在post_setup.py
目录中加入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},
...
)
在post_setup.py
:
def main():
"""Do here your post-install"""
pass
if __name__ == '__main__':
main()
有了从其目录启动setup.py
的常见想法,您将能够导入post_setup.py
否则它将启动一个空函数。
在post_setup.py
中,if __name__ == '__main__':
语句允许您从命令行手动启动安装后。
答案 3 :(得分: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()
。
答案 4 :(得分:1)
如果使用atexit,则无需创建新的cmdclass。您可以直接在setup()调用之前创建atexit寄存器。它做同样的事情。
此外,如果您需要先安装依赖项,则不不适用于pip安装,因为将在pip将软件包移到位之前调用atexit处理程序。
答案 5 :(得分:1)
我无法通过提出的任何建议解决问题,所以这对我有所帮助。
您可以调用要在安装后在setup()
中setup.py
之后运行的函数,如下所示:
from setuptools import setup
def _post_install():
<your code>
setup(...)
_post_install()
答案 6 :(得分:0)
结合@Apalala,@ Zulu和@mertyildiran的答案;这在Python 3.5环境中适用于我:
import atexit
import os
import sys
from setuptools import setup
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
def _post_install():
def find_module_path():
for p in sys.path:
if os.path.isdir(p) and my_name in os.listdir(p):
return os.path.join(p, my_name)
install_path = find_module_path()
# Add your post install code here
atexit.register(_post_install)
install.run(self)
setup(
cmdclass={'install': CustomInstall},
...
这也允许您访问install_path
中包的安装路径,以便进行一些shell工作。