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

时间:2011-02-14 19:52:33

标签: python installation dependencies packages setup.py

我有一个Python包,其setup.py具有通过常规方式声明的依赖关系,在install_requires = [...]中。其中一个软件包scikits.timeseries有一个setup.py,预计已经安装了numpy,因此,我想先用一些方法安装numpy。对于这种情况,一般情况下,可以控制依赖安装的顺序吗?怎么样?

目前,setup.py下拉依赖关系的顺序(如arg install_requires中所列)似乎几乎是随机的。另外,在setup.py设置(...)中,我尝试使用arg:

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

...没有成功,安装依赖项的顺序不受影响。

我也试过设置一个pip需求文件,但是pip安装依赖项的顺序也与需求文件的行顺序不匹配,所以没有运气。

另一种可能性是在setup.py顶部附近进行系统调用,在setup(...)调用之前安装numpy,但我希望有更好的方法。提前感谢您的帮助。

4 个答案:

答案 0 :(得分:5)

如果scikits.timeseries需要numpy,那么它应该将其声明为依赖项。如果确实如此,那么pip会为你处理事情(我很确定setuptools也会这样,但我很久没有使用它了)。如果你控制scikits.timeseries,那么你应该修复它的依赖声明。

答案 1 :(得分:0)

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

setup_requires=['numpy'],

答案 2 :(得分:0)

使用setup_requires参数,例如安装numpy之前的scipy__builtins__.__NUMPY_SETUP__ = False挂钩以正确安装numpy:

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

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

答案 3 :(得分:0)

这是一个切实可行的解决方案。这不是必须采取的过度“令人愉悦”的方法,而是“绝望的时刻...”。

基本上,您必须:

  • 覆盖setuptools的“安装命令”类(以及密切相关的类似物)
  • 通过命令行语句从脚本中执行pip操作,您可以强制执行命令

它的缺点是:

  • 必须安装点子。不能在没有环境的环境中执行setup.py
  • 出于某些奇怪的原因,未显示初始“前提”安装的控制台输出。 (也许我会在这里发布更新,以修复该问题……)

代码:

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
)