Дерево зависимостей пакетов Python
Я хотел бы проанализировать дерево зависимостей пакетов Python. Как я могу получить эти данные?
вещи, которые я уже знаю
-
setup.py
иногда содержитrequires
поле, в котором перечислены зависимости пакетов - PyPi-это онлайн-репозиторий пакетов Python
- PyPi имеет API
вещи, которые я не знаю
- очень мало проектов (около 10%) на PyPi явно зависимостей список в но все же удается установить
numpy
,pytz
, etc.... Есть ли лучший способ автоматически собрать полный список зависимостей? - есть ли где-то уже существующая база данных? Повторяю ли я существующую работу?
- существуют ли аналогичные, легкодоступные базы данных для других языки с системами распространения (R, Clojure и др...?)
3 ответов
вы должны смотреть на install_requires
поле см. и setup
ключевые слова.
requires
считается слишком расплывчатым полем для установки зависимостей. Кроме того, есть setup_requires
и test_requires
поля для зависимостей, необходимых для setup.py
и для выполнения тестов.
конечно, график зависимостей был проанализирован раньше; из этого статья в блоге Оливье Жирардо приходит это фантастическое изображение:
вот как вы можете сделать это программно, используя 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 = []
и вот как вы можете получить зависимости от API PyPi:
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))
вы можете использовать рекурсию для вызова зависимостей зависимостей, чтобы получить полное дерево. Ура!