2016-01-31 7 views
8

Sto scrivendo un po 'di codice che riporterà e riconcilia le differenze tra due installazioni python gestite da pip.Python: "pip list" in esecuzione programmatica

Come posso ottenere in modo programmatico le informazioni fornite da pip list senza eseguire un richiamo del sottoprogramma di pip?

+0

Se una lib era internamente facendo così usando il sottoprocesso sarebbe un problema? – Cripto

+0

Andrebbe bene, a patto che il mio codice non fosse tenuto a conoscere la complessità di invocare il sottoprocesso su vari sistemi con cui non ho familiarità. –

+0

OP. Ho scritto quella domanda prima di vedere la risposta di @vittore. Mi piace quella risposta. – Cripto

risposta

9

Pip è modulo appena python, quindi basta importarlo e chiamare list:

import pip 

pip.main(['list']) 

# you can get details on package using show: 

pip.main(['show', 'wheel']) 

Ok quindi non c'è modo migliore:

pip.utils.get_installed_distributions() 

si ritorna lista dei pacchetti installati.

packages = pip.utils.get_installed_distributions() 

p = packages[0] 

p.project_name 
p.version 
p.egg_name 
p.location 

Si può vedere che cosa sta facendo pip list dal codice sorgente here

anche get_installed_distributions accettare tutta una serie di parametri per restituire solo i pacchetti locali (da virtualenv corrente), ecc Si prega di consultare la Guida here.

C'è anche Sottostante comando basso livello dal modulo _vendor:

[p for p in pip._vendor.pkg_resources.working_set] 

Tuttavia get_installed_distributions forniscono più semplice api.

+0

Come posso ottenere l'output risultante? x = pip.main (['list']] imposta da x a 0 che indica l'esecuzione corretta, con i risultati che vanno a stdout. –

+0

C'è un numero di modi qui riportati: http://stackoverflow.com/questions/5136611/capture-stdout-from-a-script-in-python tuttavia non mi piacciono nessuno di loro, perché sono tutti ingombranti, lascia vedo come chiamarlo in modo leggermente diverso, – vittore

+0

@MarkHarrison, vedere la mia risposta aggiornata – vittore

1

Per completezza, ecco l'idea di vittore pip.main() arricchita con la cattura di stdout. Naturalmente utilizzando get_installed_distributions() è la soluzione preferita.

import contextlib 
@contextlib.contextmanager 
def capture(): 
    import sys 
    from cStringIO import StringIO 
    oldout,olderr = sys.stdout, sys.stderr 
    try: 
     out=[StringIO(), StringIO()] 
     sys.stdout,sys.stderr = out 
     yield out 
    finally: 
     sys.stdout,sys.stderr = oldout, olderr 
     out[0] = out[0].getvalue() 
     out[1] = out[1].getvalue() 

with capture() as out: 
    import pip 
    pip.main(['list']) 

print out 
    ['awscli (1.7.45)\nboto (2.38.0) ...