I'm trying to add a post-install task to Python distutils as described in How to extend distutils with a simple post install script?. The task is supposed to execute a Python script in the installed lib directory. This script generates additional Python modules the installed package requires.
我正在尝试向Python distutils添加安装后任务,如如何使用简单的安装后脚本扩展distutils中所述。该任务应该在已安装的lib目录中执行Python脚本。此脚本生成安装包所需的其他Python模块。
My first attempt is as follows:
我的第一次尝试如下:
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},
)
This approach works, but as far as I can tell has two deficiencies:
这种方法有效,但据我所知,有两个不足之处:
- If the user has used a Python interpreter other than the one picked up from
PATH
, the post install script will be executed with a different interpreter which might cause a problem. - It's not safe against dry-run etc. which I might be able to remedy by wrapping it in a function and calling it with
distutils.cmd.Command.execute
.
如果用户使用的Python解释器不是从PATH中获取的解释器,则安装后脚本将使用不同的解释器执行,这可能会导致问题。
它对于干运行等是不安全的,我可以通过将其包装在函数中并使用distutils.cmd.Command.execute调用它来解决这个问题。
How could I improve my solution? Is there a recommended way / best practice for doing this? I'd like to avoid pulling in another dependency if possible.
我怎样才能改进我的解决方案?这样做有推荐的方法/最佳实践吗?如果可能的话,我想避免引入另一个依赖。
2 个解决方案
#1
34
The way to address these deficiences is:
解决这些不足的方法是:
- Get the full path to the Python interpreter executing
setup.py
fromsys.executable
. -
Classes inheriting from
distutils.cmd.Command
(such asdistutils.command.install.install
which we use here) implement theexecute
method, which executes a given function in a "safe way" i.e. respecting the dry-run flag.从distutils.cmd.Command继承的类(例如我们在这里使用的distutils.command.install.install)实现了execute方法,该方法以“安全方式”执行给定函数,即遵循干运行标志。
Note however that the
--dry-run
option is currently broken and does not work as intended anyway.但请注意, - dr-run选项目前已被破坏,无论如何都无法正常工作。
获取从sys.executable执行setup.py的Python解释器的完整路径。
I ended up with the following solution:
我最终得到了以下解决方案:
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},
)
Note that I use the class name install
for my derived class because that is what python setup.py --help-commands
will use.
请注意,我为派生类使用类名安装,因为这是python setup.py --help-commands将使用的。
#2
1
I think the easiest way to perform the post-install, and keep the requirements, is to decorate the call to setup(...)
:
我认为执行安装后并保持要求的最简单方法是装饰对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=['...
)
)
This will run setup()
when declaring setup
. Once done with the requirements installation, it will run the _post_install()
function, which will run the inner function _post_actions()
.
这将在声明设置时运行setup()。完成需求安装后,它将运行_post_install()函数,该函数将运行内部函数_post_actions()。
#1
34
The way to address these deficiences is:
解决这些不足的方法是:
- Get the full path to the Python interpreter executing
setup.py
fromsys.executable
. -
Classes inheriting from
distutils.cmd.Command
(such asdistutils.command.install.install
which we use here) implement theexecute
method, which executes a given function in a "safe way" i.e. respecting the dry-run flag.从distutils.cmd.Command继承的类(例如我们在这里使用的distutils.command.install.install)实现了execute方法,该方法以“安全方式”执行给定函数,即遵循干运行标志。
Note however that the
--dry-run
option is currently broken and does not work as intended anyway.但请注意, - dr-run选项目前已被破坏,无论如何都无法正常工作。
获取从sys.executable执行setup.py的Python解释器的完整路径。
I ended up with the following solution:
我最终得到了以下解决方案:
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},
)
Note that I use the class name install
for my derived class because that is what python setup.py --help-commands
will use.
请注意,我为派生类使用类名安装,因为这是python setup.py --help-commands将使用的。
#2
1
I think the easiest way to perform the post-install, and keep the requirements, is to decorate the call to setup(...)
:
我认为执行安装后并保持要求的最简单方法是装饰对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=['...
)
)
This will run setup()
when declaring setup
. Once done with the requirements installation, it will run the _post_install()
function, which will run the inner function _post_actions()
.
这将在声明设置时运行setup()。完成需求安装后,它将运行_post_install()函数,该函数将运行内部函数_post_actions()。