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

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

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

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

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

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

person MRocklin    schedule 29.03.2013    source источник
comment
Ваш вопрос, как он есть, на самом деле слишком широк. Не задавайте слишком много вопросов в посте и делайте его практичным и содержательным. Ваш пункт 3. предполагает обсуждение и списки покупок, а не конкретные ответы.   -  person Martijn Pieters    schedule 29.03.2013


Ответы (3)


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

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

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

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

person Martijn Pieters    schedule 29.03.2013
comment
Что ж, это это очень красивый график! - person Martijn Pieters; 06.09.2013
comment
Этот график невероятен. - person Will; 08.04.2014
comment
Каким бы красивым ни был график, я не понимаю, как его читать. - person duozmo; 17.12.2015
comment
Также есть requires_dist, который я вижу в API json: pypi.python.org/pypi/Django /json Существуют пакеты, такие как криптография, которые используют `install_requires', и эта информация отсутствует в API: pypi.python.org/pypi/cryptography/json - person radtek; 27.01.2017

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

Команда:

pip install --no-install package_name

Вы можете повторно использовать часть pip в своем скрипте. За разбор требований отвечает модуль pip.req.

person vartec    schedule 29.03.2013
comment
Мне нравится идея использовать pip из Python. Интерфейс командной строки дает сбой, если у меня уже установлен пакет. Как я могу напрямую использовать код Python для поиска зависимостей определенного пакета? - person MRocklin; 29.03.2013
comment
--no-install устарел. - person Chris Martin; 05.12.2015

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

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

person radtek    schedule 27.01.2017