Подтвердить что ты не робот

Дерево зависимостей пакета Python

Я хотел бы проанализировать дерево зависимостей пакетов Python. Как я могу получить эти данные?

Вещи, которые я уже знаю

  • setup.py иногда содержит поле requires, в котором перечислены зависимости пакета
  • PyPi - это онлайн-репозиторий пакетов Python.
  • PyPi имеет API

Вещи, которые я не знаю

  • Очень мало проектов (около 10%) в PyPi явно перечисляют зависимости в поле requires, но pip/easy_install все еще удается загрузить правильные пакеты. Что мне не хватает? Например, популярная библиотека статистических вычислений pandas не перечисляет requires, но все же удается установить numpy, pytz и т.д.... Есть ли лучший способ автоматически собирать полный список зависимостей?
  • Есть ли где-то существующая база данных? Я повторяю существующую работу?
  • Существуют ли аналогичные, легко доступные базы данных для других языков с системами распространения (R, Clojure и т.д.??)
4b9b3361

Ответ 1

Вместо этого вы должны искать поле install_requires, см. Новые и измененные ключевые слова setup.

requires считается слишком расплывчатым полем, чтобы полагаться на установку зависимостей. Кроме того, существуют поля setup_requires и test_requires для зависимостей, необходимых для setup.py и для запуска тестов.

Конечно, ранее анализировался граф зависимостей; из этого статьи в блоге Оливье Жирардо приходит это фантастическое изображение:

PyPI dependencies
Изображение связано с интерактивной версией графика.

Ответ 2

Используя инструмент, например pip, вы можете перечислить все требования для каждого пакета.

Команда:

pip install --no-install package_name

Вы можете повторно использовать часть пипса в script. Часть, отвечающая за требования синтаксического анализа, - это модуль pip.req.

Ответ 3

Вот как вы можете сделать это программно с помощью пакета 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))

Вы можете использовать рекурсию для вызова зависимостей зависимостей, чтобы получить полное дерево. Ура!