21

我想分析一下Python包的依赖树。我怎样才能获得这些数据?

我已经知道的事情

  1. setup.py有时包含一个requires列出包依赖项的字段
  2. PyPi 是 Python 包的在线存储库
  3. PyPi 有一个 API

我不知道的事情

  1. PyPi 上很少有项目(大约 10%)明确列出了该requires领域的依赖关系,但pip/easy_install仍然设法下载正确的包。我错过了什么?例如,用于统计计算的流行库pandas, 没有列出requires但仍设法安装numpy,pytz等。有没有更好的方法来自动收集完整的依赖项列表?
  2. 某处是否有预先存在的数据库?我在重复现有的工作吗?
  3. 是否存在具有分发系统(R、Clojure 等...)的其他语言的类似、易于访问的数据库?
4

3 回答 3

18

您应该查看该install_requires字段请参阅新的和更改的setup关键字

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

当然,依赖图之前已经分析过了;从Olivier Girardot 的这篇博客文章中得到了这个奇妙的图像:

PyPI 依赖项
该图像链接到图形的交互式版本。

于 2013-03-29T17:57:28.993 回答
2

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

命令是:

pip install --no-install package_name

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

于 2013-03-29T18:05:55.613 回答
1

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

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))

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

于 2017-01-27T03:07:20.793 回答