Come trovare le dipendenze di un pacchetto Python


103

Come puoi ottenere a livello di codice l'elenco delle dipendenze di un pacchetto Python?

Lo standard li setup.pyha documentati, ma non riesco a trovare un modo semplice per accedervi da Python o dalla riga di comando.

Idealmente, sto cercando qualcosa come:

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

Nota, non sto parlando di importare un pacchetto e trovare tutti i moduli referenziati. Sebbene questo possa trovare la maggior parte dei pacchetti dipendenti, non sarebbe in grado di trovare il numero di versione minimo richiesto. È memorizzato solo in setup.py.


Alcune risposte qui mostrano che pip viene importato per l'uso nei programmi. La documentazione di pip sconsiglia vivamente questo utilizzo di pip. Qualcosa da tenere a mente nel caso in cui una di queste soluzioni venga utilizzata per qualcosa di importante.
Jordan Mackie

Risposte:


97

Oltre al pip show [package name]comando, c'èpipdeptree .

Basta fare

$ pip install pipdeptree

quindi corri

$ pipdeptree

e ti mostrerà le tue dipendenze in una forma ad albero, ad esempio,

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]

Il progetto si trova su https://github.com/naiquevin/pipdeptree , dove troverai anche informazioni sull'utilizzo.


7
pipdeptreemostra le dipendenze di tutti i pacchetti installati , non solo quelle di un dato pacchetto. Sebbene sia possibile filtrare il suo --jsonoutput, dipende comunque dai pacchetti già installati.
sschuberth

Vero, ma la risposta è ancora utile quando vuoi capire perché sono stati installati pacchetti che non sono nel tuo requirements.txt:)
beruic

3
Inoltre puoi utilizzare l' -popzione per selezionare solo alcuni pacchetti di cui desideri esplorare le dipendenze.
Zaccharie Ramzi

2
pipdeptreeè stato di grande aiuto durante l'ottimizzazione requirements.txt. $ pipdeptree | grep -P '^\w+' Questo produce solo pacchetti di primo livello. Maggiori informazioni qui
Lead Developer

63

Prova a usare il showcomando in pip, ad esempio:

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

Aggiorna (recupera DEPS con la versione specificata):

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
Questo ti dice la versione del pacchetto , non le sue dipendenze ; vengono solo elencati.
jonrsharpe

Vedi Requiressezione
Alex Lisovoy

3
Sì, ma non mostra "il numero di versione minimo richiesto" , poiché l'OP richiede:
jonrsharpe

1
In qualche modo $ pip3 show beautifulsoup4risulta vuoto Requires: per me - beautifulsoup4 non dipende da niente?
xealits

4
@ PythonJin, sì, a quanto pare utilizza solo pacchetti standard .. Sono rimasto un po 'sorpreso da questo. Ben fatto beautifulsoup4.
xealits

6

Alcune risposte qui mostrano che pip viene importato per l'uso nei programmi. La documentazione di pip sconsiglia vivamente questo utilizzo di pip .

Invece di accedere pkg_resourcestramite l'importazione pip, puoi effettivamente importare pkg_resourcesdirettamente e utilizzare la stessa logica (che in realtà è una delle soluzioni suggerite nei documenti pip collegati per chiunque desideri vedere le meta informazioni del pacchetto a livello di programmazione).

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

Se hai qualche problema a scoprire esattamente il nome del tuo pacchetto, l' WorkingSetistanza restituita da pkg_resources.working_setimplements__iter__ modo da poterli stampare tutti e, si spera, individuare il tuo lì :)

cioè

import pkg_resources

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

Funziona sia con python 2 che con 3 (anche se dovrai modificare le istruzioni print per python2)


3

(QUESTA È UNA RISPOSTA LEGACY E DOVREBBE ESSERE EVITATA PER LE MODERNE VERSIONI PIP E LASCIARE QUI PER RIFERIMENTO ALLE VECCHIE VERSIONI PIP) La risposta di Alex è buona (+1). In pitone:

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

dovrebbe restituire qualcosa di simile

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

dove twisted è il nome del pacchetto, che puoi trovare nel dizionario:

pip._vendor.pkg_resources.WorkingSet().entry_keys

per elencarli tutti:

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

dovrebbe darti elenchi come questo:

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

Qualcosa è cambiato nelle ultime versioni? L' _vendorattributo non sembra esistere nella versione pip 19.1.1(Modifica: va bene, sembra che sia stato spostato nel pkg_resourcespacchetto nell'ultima versione di Python!)
Prahlad Yeri

Sì, le cose sono cambiate e cercherò di aggiornarlo o rimuoverlo a favore della raccomandazione di seguito.
cgseller

La risposta di Alex è solo in parte migliore dal mio punto di vista (beh, la pip showparte è buona, non il resto). Ad ogni utilizzo pip show, pipdeptree o vedere la risposta di Jordan Mackie utilizzando setuptools ' pkg_resourcesdirettamente.
sinoroc

2

Usa https://libraries.io/ . È un buon posto per esplorare le dipendenze prima di installare utilizzando pip.

Per esempio. Digita google-cloud-storage e cerca, quindi puoi trovare la pagina per la libreria ( https://libraries.io/rubygems/google-cloud-storage ). Seleziona la versione per la quale desideri esplorare le dipendenze da "Rilasci" (l'impostazione predefinita è l'ultima), in "Dipendenze" puoi trovare l'elenco delle dipendenze e le versioni supportate.


1

Prova questo secondo questo articolo in 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)

Apparirà come:

['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']
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.