Cómo encontrar las dependencias de un paquete de Python

103

¿Cómo se puede obtener mediante programación la lista de dependencias de un paquete de Python?

El estándar los setup.pytiene documentados, pero no puedo encontrar una manera fácil de acceder a ellos desde Python o la línea de comandos.

Idealmente, estoy buscando algo como:

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

o:

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

Tenga en cuenta que no estoy hablando de importar un paquete y encontrar todos los módulos referenciados. Si bien esto podría encontrar la mayoría de los paquetes dependientes, no podría encontrar el número de versión mínimo requerido. Eso solo se almacena en setup.py.

Cerin
fuente
Algunas respuestas aquí muestran que pip se está importando para su uso en programas. La documentación de pip desaconseja fuertemente este uso de pip. Algo a tener en cuenta en caso de que alguna de estas soluciones se esté utilizando para algo importante.
Jordan Mackie

Respuestas:

97

Además del pip show [package name]comando, existe pipdeptree.

Solo haz

$ pip install pipdeptree

entonces corre

$ pipdeptree

y le mostrará sus dependencias en forma de árbol, por ejemplo,

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]

El proyecto se encuentra en https://github.com/naiquevin/pipdeptree , donde también encontrará información de uso.

beruico
fuente
7
pipdeptreemuestra las dependencias de todos los paquetes instalados , no solo las de un paquete determinado. Si bien puede filtrar su --jsonsalida, aún depende de los paquetes que ya estén instalados.
sschuberth
Es cierto, pero la respuesta sigue siendo útil cuando desea requirements.txt
saber
3
Además, puede usar la -popción para seleccionar solo unos pocos paquetes cuyas dependencias desea explorar.
Zaccharie Ramzi
2
pipdeptreefue muy útil al optimizar requirements.txt. $ pipdeptree | grep -P '^\w+' Esto genera solo paquetes de nivel superior. Más información aquí
Desarrollador principal
63

Intente usar el showcomando en pip, por ejemplo:

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

Actualizar (recuperar deps con la versión especificada):

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 Lisovoy
fuente
1
Eso le dice la versión del paquete , no sus dependencias ; simplemente aparecen en la lista.
jonrsharpe
Ver Requiressección
Alex Lisovoy
3
Sí, pero no muestra "el número de versión mínimo requerido" , ya que el OP requiere:
jonrsharpe
1
De alguna manera se $ pip3 show beautifulsoup4muestra vacío Requires: para mí, ¿no depende beautifulsoup4 de nada?
xealits
4
@PythonJin, sí, aparentemente solo usa paquetes estándar ... Me sorprendió un poco eso. Bien hecho beautifulsoup4.
xealits
6

Algunas respuestas aquí muestran que pip se está importando para su uso en programas. La documentación de pip desaconseja fuertemente este uso de pip .

En lugar de acceder a pkg_resourcestravés de la importación de pip, en realidad puede importar pkg_resourcesdirectamente y usar la misma lógica (que en realidad es una de las soluciones sugeridas en los documentos de pip vinculados para cualquiera que desee ver la metainformación del paquete mediante programación).

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

Si tiene problemas para averiguar exactamente cuál es el nombre de su paquete, la WorkingSetinstancia devuelta por los pkg_resources.working_setimplementos __iter__para que pueda imprimirlos todos y, con suerte, encontrar el suyo allí :)

es decir

import pkg_resources

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

Esto funciona con python 2 y 3 (aunque deberá ajustar las declaraciones de impresión para python2)

Jordan Mackie
fuente
3

(ESTA ES UNA RESPUESTA LEGADA Y DEBE EVITARSE PARA LAS VERSIONES DE PIP MODERNAS Y DEJARLA AQUÍ PARA REFERENCIA A VERSIONES DE PIP ANTERIORES) La respuesta de Alex es buena (+1). En Python:

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

debería devolver algo como

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

donde twisted es el nombre del paquete, que puede encontrar en el diccionario:

pip._vendor.pkg_resources.WorkingSet().entry_keys

para enumerarlos todos:

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

debería darte listas como esta:

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
fuente
¿Ha cambiado algo en las versiones recientes? El _vendoratributo no parece existir en la versión pip 19.1.1(Edición: ¡Muy bien, parece que se ha movido al pkg_resourcespaquete en la última versión de Python!)
Prahlad Yeri
Sí, las cosas han cambiado y voy a considerar actualizar esto o eliminarlo a favor de la recomendación a continuación.
cgseller
La respuesta de Alex es solo parcialmente mejor desde mi punto de vista (bueno, la pip showparte es buena, no el resto). De cualquier uso pip show, pipdeptree o ver la respuesta de Jordan Mackie usando setuptools ' pkg_resourcesdirectamente.
sinoroc
2

Utilice https://libraries.io/ . Es un buen lugar para explorar las dependencias antes de instalar usando pip.

P.ej. Escriba google-cloud-storage y busque, luego podrá encontrar la página de la biblioteca ( https://libraries.io/rubygems/google-cloud-storage ). Seleccione la versión para la que desea explorar las dependencias de las 'Versiones' (la predeterminada es la más reciente). En 'Dependencias' puede encontrar la lista de dependencias y sus versiones compatibles.

Praboda
fuente
1

Prueba esto de acuerdo con este artículo en 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)

Se mostrará como:

['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
fuente