Как найти зависимости пакета Python

106

Как программно получить список зависимостей пакета Python?

В стандарте setup.pyони задокументированы, но я не могу найти простой способ получить к нему доступ ни из Python, ни из командной строки.

В идеале я ищу что-то вроде:

$ pip install somepackage --only-list-deps
kombu>=3.0.8
billiard>=3.3.0.13
boto>=2.26

или:

>>> import package_deps
>>> package = package_deps.find('somepackage')
>>> print package.dependencies
['kombu>=3.0.8', 'billiard>=3.3.0.13', 'boto>=2.26']

Обратите внимание, я не говорю об импорте пакета и поиске всех модулей, на которые есть ссылки. Хотя он может найти большинство зависимых пакетов, он не сможет найти требуемый минимальный номер версии. Это хранится только в setup.py.

Cerin
источник
Довольно много ответов здесь показывают, что pip импортируется для использования в программах. Документация пип сильно отговаривает от этого использования ПУМ. О чем следует помнить, если какое-либо из этих решений используется для чего-то важного.
Jordan Mackie

Ответы:

97

Помимо pip show [package name]команды есть pipdeptree.

Просто сделать

$ pip install pipdeptree

затем беги

$ pipdeptree

и он покажет вам ваши зависимости в виде дерева, например,

flake8==2.5.0
  - mccabe [required: >=0.2.1,<0.4, installed: 0.3.1]
  - pep8 [required: !=1.6.0,>=1.5.7,!=1.6.1,!=1.6.2, installed: 1.5.7]
  - pyflakes [required: >=0.8.1,<1.1, installed: 1.0.0]
ipdb==0.8
  - ipython [required: >=0.10, installed: 1.1.0]

Проект находится по адресу https://github.com/naiquevin/pipdeptree , где вы также найдете информацию об использовании.

Beruic
источник
7
pipdeptreeпоказать зависимости всех установленных пакетов, а не только для данного пакета. Хотя вы можете фильтровать его--json вывод, он по-прежнему зависит от уже установленных пакетов.
sschuberth 01
Верно, но ответ по-прежнему полезен, если вы хотите понять, почему были установлены пакеты, которых нет у вас requirements.txt:)
beruic 01
3
Кроме того, вы можете использовать -p опцию, чтобы выбрать только несколько пакетов, зависимости которых вы хотите изучить.
Zaccharie Ramzi
2
pipdeptreeбыл очень полезным при оптимизации requirements.txt. $ pipdeptree | grep -P '^\w+' Это выводит только пакеты верхнего уровня. Подробнее здесь
ведущий разработчик
64

Попробуйте использовать showкоманду pip, например:

$ pip show tornado
---
Name: tornado
Version: 4.1
Location: *****
Requires: certifi, backports.ssl-match-hostname

Обновить (получить данные с указанной версией):

from pip._vendor import pkg_resources


_package_name = 'somepackage'
_package = pkg_resources.working_set.by_key[_package_name]

print([str(r) for r in _package.requires()])  # retrieve deps from setup.py

Output: ['kombu>=3.0.8', 
         'billiard>=3.3.0.13', 
         'boto>=2.26']
Алексей Лисовой
источник
1
Это сообщает вам версию пакета , а не его зависимости ; они просто попадают в список.
jonrsharpe
Смотрите Requiresраздел
Alex Lisovoy
3
Да, но он не показывает «минимальный необходимый номер версии» , как того требует OP:
jonrsharpe
1
Как-то у меня $ pip3 show beautifulsoup4показывает пусто Requires: - beautifulsoup4 ни от чего не зависит?
xealits
4
@PythonJin, да, очевидно, он использует только стандартные пакеты .. Я был немного удивлен этим. Молодцы, beautifulsoup4.
xealits
6

Довольно много ответов здесь показывают, что pip импортируется для использования в программах. Документация пип сильно отговаривает от этого использования ПУМ .

Вместо доступа pkg_resourcesчерез импорт pip вы можете просто импортировать pkg_resourcesнапрямую и использовать ту же логику (что на самом деле является одним из предлагаемых решений в связанных документах pip для всех, кто хочет программно просматривать метаинформацию пакета).

import pkg_resources

_package_name = 'yourpackagename'

def get_dependencies_with_semver_string():
    package = pkg_resources.working_set.by_key[_package_name]
    return [str(r) for r in package.requires()]

Если у вас возникли проблемы с точным определением имени вашего пакета, WorkingSetэкземпляр, возвращаемый функцией, pkg_resources.working_setреализует__iter__ вы можете распечатать их все и, надеюсь, найти там свой :)

т.е.

import pkg_resources

def print_all_in_working_set():
    ws = pkg_resources.working_set
    for package_name in ws:
        print(ws)

Это работает как с python 2, так и с 3 (хотя вам нужно настроить операторы печати для python2)

Джордан Маки
источник
3

(ЭТО УСТАРЕВШИЙ ОТВЕТ, СЛЕДУЕТ ИЗБЕГАТЬ ДЛЯ СОВРЕМЕННЫХ ВЕРСИЙ PIP И ОСТАВЛЯЙТЕСЬ ЗДЕСЬ ДЛЯ СМОТРЕНИЯ НА СТАРЫЕ ВЕРСИИ PIP) Ответ Алекс хороший (+1). В питоне:

pip._vendor.pkg_resources.working_set.by_key['twisted'].requires()

должен вернуть что-то вроде

[Requirement.parse('zope.interface>=3.6.0')]

где twisted - название пакета, которое вы можете найти в словаре:

pip._vendor.pkg_resources.WorkingSet().entry_keys

чтобы перечислить их все:

dict = pip._vendor.pkg_resources.WorkingSet().entry_keys
for key in dict:
    for name in dict[key]:
        req =pip._vendor.pkg_resources.working_set.by_key[name].requires()
        print('pkg {} from {} requires {}'.format(name,
                                                  key,
                                                  req))

должен дать вам такие списки:

pkg pyobjc-framework-syncservices from /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC requires [Requirement.parse('pyobjc-core>=2.5.1'), Requirement.parse('pyobjc-framework-Cocoa>=2.5.1'), Requirement.parse('pyobjc-framework-CoreData>=2.5.1')]
cgseller
источник
Что-то изменилось в последних версиях? _vendorАтрибут , кажется, не существует в пип версии 19.1.1(Edit: Хорошо, это , кажется, переехал в pkg_resourcesпакет в последней версии питона!)
Прахлад Ери
Да, все изменилось, и я собираюсь либо обновить это, либо удалить его в пользу рекомендации ниже.
cgseller
С моей точки зрения, ответ Алекса лучше только отчасти (ну, pip show часть, а не все остальное). Либо использовать pip show, pipdeptree или увидеть ответ Jordan Mackie, используя Setuptools ' pkg_resourcesнепосредственно.
sinoroc
2

Используйте https://libraries.io/ . Это хорошее место для изучения зависимостей перед установкой с помощью pip.

Например. Введите google-cloud-storage и выполните поиск, после чего вы сможете найти страницу библиотеки ( https://libraries.io/rubygems/google-cloud-storage ). Выберите версию, для которой вы хотите изучить зависимости, из «Релизов» (по умолчанию - последняя версия). В «Зависимости» вы можете найти список зависимостей и их поддерживаемые версии.

Прабода
источник
1

Попробуйте это в соответствии с этой статьей на Python:

import pip 
installed_packages = pip.get_installed_distributions()
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
     for i in installed_packages]) 
print(installed_packages_list)

Это будет выглядеть так:

['behave==1.2.4', 'enum34==1.0', 'flask==0.10.1', 'itsdangerous==0.24', 
 'jinja2==2.7.2', 'jsonschema==2.3.0', 'markupsafe==0.23', 'nose==1.3.3', 
 'parse-type==0.3.4', 'parse==1.6.4', 'prettytable==0.7.2', 'requests==2.3.0',
 'six==1.6.1', 'vioozer-metadata==0.1', 'vioozer-users-server==0.1', 
 'werkzeug==0.9.4']
EniGma
источник