In setup.py or pip requirements file, how to contr

2019-02-09 01:19发布

I've got a Python package with its setup.py having dependencies declared via the usual way, in 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. 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. Also, in the setup.py setup(...) I tried using the 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.

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. Thanks in advance for any help.

4条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-02-09 01:36

Use setup_requires parameter, for instance to install numpy prior scipy and __builtins__.__NUMPY_SETUP__ = False hook to get numpy installed correctly:

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

def run(self):
    __builtins__.__NUMPY_SETUP__ = False
    import numpy
查看更多
手持菜刀,她持情操
3楼-- · 2019-02-09 01:41

You can add numpy to setup_requires section:

setup_requires=['numpy'],
查看更多
Juvenile、少年°
4楼-- · 2019-02-09 01:44

If scikits.timeseries needs numpy, then it should declare it as a dependency. 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). If you control scikits.timeseries, then you should fix it's dependency declarations.

查看更多
走好不送
5楼-- · 2019-02-09 01:58

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)
  • Execute pip from the script via command line statements for which you can enforce the order

The drawbacks to this are:

  • Pip must be installed. You can't just execute setup.py in an environment without that.
  • 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
)
查看更多
登录 后发表回答