Identifying the dependency relationship for python packages installed with pip
当我执行pip冻结时,我看到大量没有显式安装的python包,例如。
1 2 3 4 5 6 7 8 9 10 11 | $ 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,我不想依赖一个包,直到我知道更多关于不意外卸载或升级它的信息。
您可以尝试PIPDEPTREE,它将依赖项显示为树结构,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | $ 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 |
让它运行:
1 | pip install pipdeptree |
编辑:正如@esteban在评论中所指出的,您还可以将树与
1 2 3 | $ pipdeptree -r -p Werkzeug Werkzeug==0.11.15 - Flask==0.12 [requires: Werkzeug>=0.7] |
1 2 3 4 5 6 7 8 | $ pip show specloud Package: specloud Version: 0.4.4 Requires: nose figleaf pinocchio |
在PIP版本1.4RC5中引入了
正如我最近在一个hn线程上所说,我将推荐以下内容:
有一个带有您主要依赖项的注释
1 2 | ## this is needed for whatever reason package1 |
安装您的依赖项:
1 2 3 4 5 6 | ## 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 URL被蛋名称替换。
- 依赖项的依赖项仍然按字母顺序排序,因此您不直接知道哪个包需要哪个包,但此时您并不真正需要它。
- 使用
pip install --no-install 列出具体要求。 - 如果没有,请使用virtualenv。
您还可以使用一个单行命令,将需求中的包传输到pip show。
1 | cut -d'=' -f1 requirements.txt | xargs pip show |
首先,
其次,python包确实包含有关依赖包以及所需版本的信息。您可以使用这里描述的方法看到特定pkg的依赖性。当您升级包时,像pip这样的安装程序脚本将为您处理依赖项的升级。
为了解决包的更新问题,我建议使用PIP需求文件。您可以定义所需的软件包和版本,并使用pip install立即安装它们。
我写了一个快速脚本来解决这个问题。以下脚本将显示任何给定包的父(依赖)包。通过这种方式,您可以确保升级或安装任何特定包都是安全的。其用途如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #!/usr/bin/env 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._internal.utils.misc.get_installed_distributions(): for requirement_package in package.requires(): requirement_name = requirement_package.project_name if requirement_name == target_name: yield package.project_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))) |
(解决方法,不是正确答案)
有同样的问题,LXML没有安装,我想知道谁需要LXML。不是LXML需要的人。最终绕过了这个问题。
注意我的网站包放在哪里。
到那里,递归grep进行导入(最后一个grep的--invert match用于从考虑中删除lxml自己的文件)。
是的,对于如何使用PIP来完成这项工作,我没有给出答案,但是我没有从这里的建议中得到任何成功,不管是什么原因。
1 | site-packages me$ egrep -i --include=*.py -r -n lxml . | grep import | grep --invert-match /lxml/ |