Идентификация отношения зависимостей для пакетов python, установленных с помощью pip
Когда я делаю зависание в пипе, я вижу большое количество пакетов Python, которые я явно не устанавливал, например.
$ pip freeze
Cheetah==2.4.3
GnuPGInterface==0.3.2
Landscape-Client==11.01
M2Crypto==0.20.1
PAM==0.4.2
PIL==1.1.7
PyYAML==3.09
Twisted-Core==10.2.0
Twisted-Web==10.2.0
(etc.)
Есть ли способ определить, почему pip установил эти конкретные зависимые пакеты? Другими словами, как определить родительский пакет, в котором эти пакеты были зависимыми?
Например, я могу использовать Twisted, и я не хочу зависеть от пакета, пока не узнаю больше о том, что вы случайно не удалили его или не обновили.
Ответы
Ответ 1
Вы можете попробовать pipdeptree, который отображает зависимости как древовидную структуру, например:
$ pipdeptree
Lookupy==0.1
wsgiref==0.1.2
argparse==1.2.1
psycopg2==2.5.2
Flask-Script==0.6.6
- Flask [installed: 0.10.1]
- Werkzeug [required: >=0.7, installed: 0.9.4]
- Jinja2 [required: >=2.4, installed: 2.7.2]
- MarkupSafe [installed: 0.18]
- itsdangerous [required: >=0.21, installed: 0.23]
alembic==0.6.2
- SQLAlchemy [required: >=0.7.3, installed: 0.9.1]
- Mako [installed: 0.9.1]
- MarkupSafe [required: >=0.9.2, installed: 0.18]
ipython==2.0.0
slugify==0.0.1
redis==2.9.1
Чтобы запустить его:
pip install pipdeptree
EDIT:, как отметил @Esteban в комментариях, вы также можете перечислить дерево в обратном порядке с помощью -r
или для одного пакета с -p <package_name>
, чтобы найти, что установил Werkzeug, который вы могли запустить:
$ pipdeptree -r -p Werkzeug
Werkzeug==0.11.15
- Flask==0.12 [requires: Werkzeug>=0.7]
Ответ 2
Команда pip show
покажет, какие пакеты необходимы для указанного пакета (обратите внимание, что указанный пакет уже должен быть установлен):
$ pip show specloud
Package: specloud
Version: 0.4.4
Requires:
nose
figleaf
pinocchio
pip show
был введен в pip версии 1.4rc5
Ответ 3
Как я недавно сказал в hn thread, я рекомендую следующее:
Отметьте requirements.txt
файл с вашими основными зависимостями:
## this is needed for whatever reason
package1
Установите свои зависимости: pip install -r requirements.txt
.
Теперь вы получаете полный список своих зависимостей с помощью pip freeze -r requirements.txt
:
## this is needed for whatever reason
package1==1.2.3
## The following requirements were added by pip --freeze:
package1-dependency1==1.2.3
package1-dependency1==1.2.3
Это позволяет сохранить структуру файла с комментариями, красиво отделяя ваши зависимости от зависимостей ваших зависимостей. Таким образом, у вас будет гораздо приятнее время, необходимое для удаления одного из них:)
Обратите внимание на следующее:
- У вас может быть чистый
requirements.raw
с контролем версий, чтобы перестроить ваш полный requirements.txt
.
- Остерегайтесь ссылок git, заменяемых именами яиц в процессе.
- Зависимости ваших зависимостей по-прежнему сортируются по алфавиту, поэтому вы напрямую не знаете, какой из них требуется для какого пакета, но на данный момент вам это действительно не нужно.
- Используйте
pip install --no-install <package_name>
для указания конкретных требований.
- Используйте virtualenv, если вы этого не сделаете.
Ответ 4
Вы также можете использовать команду с одной строкой, которая передает пакеты в требованиях к показам pip.
cut -d'=' -f1 requirements.txt | xargs pip show
Ответ 5
Прежде всего pip freeze
отображает все установленные на данный момент пакеты Python, не обязательно используя PIP.
Во-вторых, пакеты Python содержат информацию об зависимых пакетах, а также необходимые версии. Вы можете увидеть зависимости конкретного pkg с помощью описанных здесь методов . Когда вы обновляете пакет, установщик script, такой как PIP, будет обрабатывать обновления для вас.
Чтобы решить обновление пакетов, я рекомендую использовать файлы требований PIP. Вы можете определить, какие пакеты и версии вам понадобятся, и установить их сразу с помощью установки pip.
Ответ 6
Я написал быстрый script, чтобы решить эту проблему. Следующий script отобразит родительский (зависимый) пакет для любого данного пакета. Таким образом, вы можете быть уверены, что безопасно обновлять или устанавливать какой-либо конкретный пакет. Его можно использовать следующим образом: dependants.py PACKAGENAME
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Find dependants of a Python package"""
import logging
import pip
import pkg_resources
import sys
__program__ = 'dependants.py'
def get_dependants(target_name):
for package in pip.get_installed_distributions():
for requirement_package in package.requires():
requirement_name = requirement_package.project_name
if requirement_name == target_name:
package_name = package.project_name
yield package_name
# configure logging
logging.basicConfig(format='%(levelname)s: %(message)s',
level=logging.INFO)
try:
target_name = sys.argv[1]
except IndexError:
logging.error("missing package name")
sys.exit(1)
try:
pkg_resources.get_distribution(target_name)
except pkg_resources.DistributionNotFound:
logging.error("'%s' is not a valid package", target_name)
sys.exit(1)
print(list(get_dependants(target_name)))
Ответ 7
(обходной путь, а не истинный ответ)
Имела ту же проблему, когда lxml не устанавливался, и мне хотелось знать, кому нужен lxml. Не нужен lxml. Закончено обход проблемы.
-
отметив, куда были помещены пакеты моего сайта.
-
Перейдите туда и рекурсивный grep для импорта (последний grep -invert-match служит для удаления lxml собственных файлов из соображений).
Да, не ответ на вопрос, как использовать pip для этого, но я не получил никакого успеха из предложений здесь, по любой причине.
site-packages me$ egrep -i --include=*.py -r -n lxml . | grep import | grep --invert-match /lxml/