Python包依赖树

时间:2013-03-29 17:56:21

标签: python dependency-management pypi

我想分析Python包的依赖树。我如何获得这些数据?

我已经知道的事情

  1. setup.py有时会包含列出包依赖关系的requires字段
  2. PyPi是Python包的在线存储库
  3. PyPi有一个API
  4. 我不知道的事情

    1. PyPi中很少有项目(大约10%)明确列出requires字段中的依赖项,但pip/easy_install仍设法下载正确的软件包。我错过了什么?例如,流行的统计计算库pandas未列出requires,但仍设法安装numpypytz等....是否有更好的自动收集完整的依赖列表的方法?
    2. 某处有预先存在的数据库吗?我是否重复现有的工作?
    3. 对于配有分销系统的其他语言(R,Clojure等等),是否存在类似,易于访问的数据库?

3 个答案:

答案 0 :(得分:18)

您应该查看install_requires字段而不是,请参阅New and changed setup keywords

requires被视为依赖于依赖安装的字段过于模糊。此外,setup_requires和运行测试所需的依赖项有test_requiressetup.py个字段。

当然,之前已经分析了依赖图;从这个blog article by Olivier Girardot来看这个梦幻般的形象:

PyPI dependencies
图像链接到图表的交互式版本。

答案 1 :(得分:2)

使用pip之类的工具,您可以列出每个包的所有要求。

命令是:

pip install --no-install package_name

您可以在脚本中重复使用pip的一部分。负责解析需求的部分是模块pip.req

答案 2 :(得分:0)

以下是使用python pip包以编程方式执行此操作的方法:

from pip._vendor import pkg_resources  # Ensure pip conf index-url pointed to real PyPi Index

# Get dependencies from pip 
package_name = 'Django'
try:
    package_resources = pkg_resources.working_set.by_key[package_name.lower()] # Throws KeyError if not found
    dependencies = package_resources._dep_map.keys() + ([str(r) for r in package_resources.requires()])
    dependencies = list(set(dependencies))
except KeyError:
    dependencies = []

以下是如何从PyPi API获取依赖关系:

import requests
import json
package_name = 'Django'
# Package info url
PYPI_API_URL = 'https://pypi.python.org/pypi/{package_name}/json'
package_details_url = PYPI_API_URL.format(package_name=package_name)
response = requests.get(package_details_url)
data = json.loads(response.content)
if response.status_code == 200:
    dependencies = data['info'].get('requires_dist')
    dependencies2 = data['info'].get('requires')
    dependencies3 = data['info'].get('setup_requires')
    dependencies4 = data['info'].get('test_requires')
    dependencies5 = data['info'].get('install_requires')
    if dependencies2:
        dependencies.extend(dependencies2)
    if dependencies3:
        dependencies.extend(dependencies3)
    if dependencies4:
        dependencies.extend(dependencies4)
    if dependencies5:
        dependencies.extend(dependencies5)
    dependencies = list(set(dependencies))

您可以使用递归来调用依赖项的依赖项来获取完整的树。干杯!