如何在setup.py中访问setuptools的install_requires安装的模块?

时间:2016-01-28 14:49:36

标签: python installation setuptools setup.py pkg-resources

我正在编写一个setup.py来安装我的包reboundx,它只有一个依赖项rebound。我的包构建了一个扩展libreboundx.so,需要链接到setup.py

中的librebound.so
rebxExt = Extension('libreboundx', libraries=['rebound'], library_dirs = [rebound_path]...)

我希望能够在install_requires调用中使用setup(...)来构建reboundx模块,以确保安装了rebound的正确版本。有没有办法解决循环问题?

如果未安装rebound,我会以某种方式需要setuptools通过install_requires检测到这一点,安装rebound,然后找到正确的路径并构建扩展程序libreboundx.so

3 个答案:

答案 0 :(得分:1)

(如果你喜欢这种方法,我可以进一步阐述) 考虑这个例子。我使用ctypes加载共享库。然后使用函数调用获取库的版本。

>>> import ctypes
>>> x = ctypes.cdll.LoadLibrary("libc.so.6")
>>> x.gnu_get_libc_version
<_FuncPtr object at 0x7f9a08e3e460>
>>> getversion = x.gnu_get_libc_version
>>> getversion.restype = ctypes.c_char_p
>>> getversion()
'2.19'

你可以用反弹做类似的东西。使用try语句加载librebound。 如果它是错误的版本或者在库的标准搜索路径中找不到,则编译librebound。

#setup.py
import ctypes
try:
    x = ctypes.cdll.LoadLibrary("librebound.so")
    x.restype = ctypes.c_char_p
    version = x.get_version()
    major,minor = version.split(".")
    if int(major) < REQUIRED_VERSION:
        raise False, "LIBREBOUND VERSION %s IS NOT SUPPORTED"%(str(version))

except:
    pass
    #invoke rebound's makefile
    #probably install the new library to lib path.
    #link to new rebound 

rebxExt = Extension('libreboundx', libraries=['rebound'], library_dirs = [rebound_path]...)

答案 1 :(得分:1)

您应该使用setup_requires参数setup()。来自文档,

  

setup_requires

     

字符串或字符串列表,指定为了运行安装脚本而需要存在的其他分发。在处理其余的安装脚本或命令之前,setuptools将尝试获取这些(甚至可以使用EasyInstall下载它们)。如果您在构建过程中使用distutils扩展,则需要此参数;例如,处理setup()参数并将它们转换为EGG-INFO元数据文件的扩展。

     

(注意:setup_requires中列出的项目不会自动安装在运行安装脚本的系统上。如果它们本地不可用,则只需将它们下载到./.eggs目录。如果需要它们要安装,以及在运行安装脚本时可用,您应该将它们添加到install_requires和setup_requires。)

https://pythonhosted.org/setuptools/setuptools.html#new-and-changed-setup-keywords

修改: 它应该为setup_requires中的每个条目创建一个egg目录。 然而,我只是尝试了反弹,实际上无法在简易安装下构建。

$> python2 setup.py install
install_dir .
warning: no files found matching 'src/rebound.h'
src/rebound.c:38:21: fatal error: rebound.h: No such file or directory
compilation terminated.
Traceback (most recent call last):
  File "setup.py", line 187, in <module>
    url="http://www.mathics.github.io/",   # project home page, if any
  File "/usr/lib/python2.7/distutils/core.py", line 111, in setup
    _setup_distribution = dist = klass(attrs)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/dist.py", line 221, in __init__
    self.fetch_build_eggs(attrs.pop('setup_requires'))
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/dist.py", line 245, in fetch_build_eggs
    parse_requirements(requires), installer=self.fetch_build_egg
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/pkg_resources.py", line 544, in resolve
    dist = best[req.key] = env.best_match(req, self, installer)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/pkg_resources.py", line 786, in best_match
    return self.obtain(req, installer) # try and download/install
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/pkg_resources.py", line 798, in obtain
    return installer(requirement)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/dist.py", line 293, in fetch_build_egg
    return cmd.easy_install(req)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/command/easy_install.py", line 582, in easy_install
    return self.install_item(spec, dist.location, tmpdir, deps)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/command/easy_install.py", line 612, in install_item
    dists = self.install_eggs(spec, download, tmpdir)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/command/easy_install.py", line 802, in install_eggs
    return self.build_and_install(setup_script, setup_base)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/command/easy_install.py", line 1079, in build_and_install
    self.run_setup(setup_script, setup_base, args)
  File "/usr/lib/python2.7/site-packages/distribute-0.6.14-py2.7.egg/setuptools/command/easy_install.py", line 1070, in run_setup
    raise DistutilsError("Setup script exited with %s" % (v.args[0],))
distutils.errors.DistutilsError: Setup script exited with error: command 'gcc' failed with exit status 1

答案 2 :(得分:1)

似乎setuptools通过setup_requires关键字实现了这一点,正如sn6uv所指出的那样。但是,我发现很难找到展示如何使用它的文档和/或示例。从我的确发现,对于没有经验的人来说,它似乎也有点微妙/复杂。

首先,使用pip时,setup_requires中的依赖项安装方式与其他所有内容的安装方式不同(请参阅Install package which has setup_requires from local source distributions)。看起来如果你需要在setup.py中导入依赖项,你需要继承install命令,以便延迟导入直到它可用(深入到distutils邮件列表上的一个主题争论setup_requires,Donald Stufft谈到这个和链接到一个例子:https://mail.python.org/pipermail/distutils-sig/2015-March/025882.html)。

所以我放弃并实施了类似于goCards建议的手动检查。只是想我会发布更多雄心勃勃的人的链接。