简体   繁体   English

在 setup.py 或 pip 需求文件中,如何控制安装包依赖的顺序?

[英]In setup.py or pip requirements file, how to control order of installing package dependencies?

I've got a Python package with its setup.py having dependencies declared via the usual way, in install_requires=[...].我有一个 Python 包,它的 setup.py 在 install_requires=[...] 中通过通常的方式声明了依赖项。 One of the packages there, scikits.timeseries, has a setup.py expecting numpy to already be installed, thus, I'd like some way to have numpy installed first.其中一个包 scikits.timeseries 有一个 setup.py,期望 numpy 已经安装,因此,我想先安装 numpy。 For this case and in general, can the order of dependency installation be controlled?对于这种情况和一般情况,是否可以控制依赖项安装的顺序? How?怎么样?

Currently the order in which setup.py pulls down dependencies (as listed in the arg install_requires) seems practically random.目前 setup.py 拉下依赖项的顺序(如 arg install_requires 中所列)似乎几乎是随机的。 Also, in the setup.py setup(...) I tried using the arg:另外,在 setup.py setup(...) 我尝试使用 arg:

extras_require={'scikits.timeseries': ['numpy']}

...without success, the order of installing dependencies was unaffected. ...没有成功,安装依赖项的顺序不受影响。

I also tried setting up a pip requirements file, but there too, pip's order of installing dependencies didn't match the line-order of the requirements file, so no luck.我也尝试设置一个 pip 需求文件,但在那里,pip 安装依赖项的顺序与需求文件的行顺序不匹配,所以没有运气。

Another possibility would be to have a system call near the top of setup.py, to install numpy before the setup(...) call, but I hope there's a better way.另一种可能性是在 setup.py 顶部附近有一个系统调用,在 setup(...) 调用之前安装 numpy,但我希望有更好的方法。 Thanks in advance for any help.在此先感谢您的帮助。

If scikits.timeseries needs numpy , then it should declare it as a dependency.如果scikits.timeseries需要numpy ,则应将其声明为依赖项。 If it did, then pip would handle things for you (I'm pretty sure setuptools would, too, but I haven't used it in a long while).如果是这样,那么pip会为你处理事情(我很确定setuptools也会,但我已经很久没有使用它了)。 If you control scikits.timeseries , then you should fix it's dependency declarations.如果您控制scikits.timeseries ,那么您应该修复它的依赖声明。

Use setup_requires parameter, for instance to install numpy prior scipy put it into setup_requires and add __builtins__.__NUMPY_SETUP__ = False hook to get numpy installed correctly:使用setup_requires参数,例如安装numpy之前的scipy将其放入 setup_requires 并添加__builtins__.__NUMPY_SETUP__ = False hook 以正确安装 numpy:

setup(
    name='test',
    version='0.1',
    setup_requires=['numpy'],
    install_requires=['scipy']
)

def run(self):
    __builtins__.__NUMPY_SETUP__ = False
    import numpy

Here's a solution which actually works.这是一个实际有效的解决方案。 It's not an overly "pleasant" method to have to resort to, but "desperate times...".这不是一种过于“令人愉快”的方法,而是“绝望的时代......”。

Basically, you have to:基本上,您必须:

  • Override the setuptools "install command" class (plus the closely related analogs)覆盖 setuptools“安装命令”类(加上密切相关的类似物)
  • Execute pip from the script via command line statements for which you can enforce the order通过命令行语句从脚本执行 pip,您可以执行命令

The drawbacks to this are:这样做的缺点是:

  • Pip must be installed.必须安装pip。 You can't just execute setup.py in an environment without that.你不能只在没有它的环境中执行setup.py
  • The console output of the initial "prerequisite" installs don't appear for some weird reason.由于某些奇怪的原因,初始“先决条件”安装的控制台输出不会出现。 (Perhaps I'll post an update here down the line fixing that...) (也许我会在这里发布更新来解决这个问题......)

The code:代码:

from setuptools import setup

# Override standard setuptools commands. 
# Enforce the order of dependency installation.
#-------------------------------------------------
PREREQS = [ "ORDERED-INSTALL-PACKAGE" ]

from setuptools.command.install import install
from setuptools.command.develop import develop
from setuptools.command.egg_info import egg_info

def requires( packages ): 
    from os import system
    from sys import executable as PYTHON_PATH
    from pkg_resources import require
    require( "pip" )
    CMD_TMPLT = '"' + PYTHON_PATH + '" -m pip install %s'
    for pkg in packages: system( CMD_TMPLT % (pkg,) )       

class OrderedInstall( install ):
    def run( self ):
        requires( PREREQS )
        install.run( self )        

class OrderedDevelop( develop ):
    def run( self ):
        requires( PREREQS )
        develop.run( self )        

class OrderedEggInfo( egg_info ):
    def run( self ):
        requires( PREREQS )
        egg_info.run( self )        

CMD_CLASSES = { 
     "install" : OrderedInstall
   , "develop" : OrderedDevelop
   , "egg_info": OrderedEggInfo 
}        
#-------------------------------------------------

setup ( 
     ...
    install_requires = [ "UNORDERED-INSTALL-PACKAGE" ],
    cmdclass = CMD_CLASSES
)

您可以将 numpy 添加到 setup_requires 部分:

setup_requires=['numpy'],

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM