如何找到 Python 包的依赖项

如何以编程方式获得 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 中。

148659 次浏览

尝试在 pip中使用 show命令,例如:

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

更新 (检索指定版本的 deps) :

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']

(这是一个遗留的答案,应该避免现代管道版本和留在这里参考旧管道版本) Alex 的回答很好(+ 1)在 python 中:

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

应该返回类似于

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

在这里,你可以在字典里找到软件包的名字:

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')]

除了 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,您还可以在其中找到使用信息。

试试这个根据这个 文章在 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']

这里的很多答案显示 pip 被导入用于程序。

不需要通过 pip 导入访问 pkg_resources,实际上你可以直接导入 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()]

如果在查找软件包的确切名称时遇到一些麻烦,那么 pkg_resources.working_set返回的 WorkingSet实例实现了 __iter__,因此您可以打印所有这些实例,并希望在其中找到您的实例:)

也就是说。

import pkg_resources


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

这同时适用于 python2和3(尽管您需要调整 python2的 print 语句)。

使用 https://libraries.io/。在使用 pip 安装之前,这是一个探索依赖关系的好地方。

艾格。输入 google-cloud-Storage and search,然后您可以找到图书馆的页面(https://libraries.io/rubygems/google-cloud-storage)。选择您想要从‘ Relases’(默认是最新版本)中探索依赖关系的版本,在‘ Dependency’下您可以找到依赖关系列表及其支持的版本。

关于在 Windows 机器上找到和测试的方法的简要概述:

  1. 解析 PyPI: https://pypi.org/pypi/<package>/<version>/json(第七)的 json 文件

  2. 检查 /site-packages/<package-version>.dist-info/METADATA(# 13,需要预安装)

  3. 已弃用(# 11)

  4. 已弃用(12号)

  5. pip show <package>(# 1# 2,需要预安装)

  6. 使用 import pippip._vendor.pkg_resources编写一个脚本: 弃用(# 6)

  7. 使用 setuptools包的 import pkg_resources编写一个脚本(# 4,需要预先安装)

  8. 检查 https://libraries.io/(# 5)

  9. 使用 pipdeptree软件包(# 3# 8,需要预先安装)

  10. 使用 Johnnydep包(10英镑) : 在许多情况下测试挂起。

  11. 已弃用(第九名)

  12. conda search [package_name] --info

    • 可以列出其他软件包: vc2015_runtimepython_abilibflang等等。
    • 注意,这个方法可以根据构建和通道列出不同的包
django 3.2 pyhd3eb1b0_0
-----------------------
file name   : django-3.2-pyhd3eb1b0_0.conda
...
timestamp   : 2021-04-06 20:19:41 UTC
dependencies:
- asgiref
- psycopg2
- python
- pytz
- sqlparse


django 3.2 pyhd8ed1ab_0
-----------------------
file name   : django-3.2-pyhd8ed1ab_0.tar.bz2
...
timestamp   : 2021-04-07 21:15:25 UTC
dependencies:
- asgiref >=3.3.2,<4
- python >=3.6
- pytz
- sqlparse >=0.2.2

还有一点需要注意的是,每个方法可以提供不同的结果。

例如,需要 requests/setup.py chardet0 chardetidnaurllib3certifi。此外,额外的包 pyOpenSSLcryptographysocksPySockswin-inet-pton可能需要。

  • 方法1和方法2与之相符。
  • 方法8只是列出所有的依赖项(按下探索依赖项按钮只是挂起)。
  • 方法12只列出 chardetidnaurllib3certifi
  • 如果在 Linux docker 中使用 pip安装 requests,则方法5和7不列出任何依赖项。
  • 方法如果 requests安装在 Windows 机器的 conda 环境中,则列出 chardetidnaurllib3certifi

有一个很好的工具 Johnnydep。它的好处是不必安装要检查的包。

pip install johnnydep

像这样使用:

johnnydep deepspeech-tflite

标准库提供 importlib.metadata.requires()自3.8版本及以后的版本:

In [1]: from importlib.metadata import requires


In [2]: requires('pytype')
Out[2]:
['attrs (>=21.2.0)',
'importlab (>=0.6.1)',
'libcst',
'ninja (>=1.10.0.post2)',
'pyyaml (>=3.11)',
'six',
'tabulate',
'toml',
'typed-ast (>=1.4.3)',
'dataclasses ; python_version < "3.7"']

对于旧版本的 Python,有 importlib-metadata可用。

如果需要解析由 requires()返回的字符串,我强烈建议使用 packaging库,因为它的 packaging.requirements模块是 PEP 508的参考实现。具有复杂依赖关系规范字符串的示例:

In [3]: from packaging.requirements import Requirement


In [4]: spec = 'requests [security,test] (>=2.21.0) ; implementation_name == "cpython"'


In [5]: r = Requirement(spec)


In [6]: r.name
Out[6]: 'requests'


In [7]: r.specifier
Out[7]: <SpecifierSet('>=2.21.0')>


In [8]: r.extras
Out[8]: {'security', 'test'}


In [9]: r.marker
Out[9]: <Marker('implementation_name == "cpython"')>