Python: ejecutando programáticamente la “lista pip”

Estoy escribiendo un poco de código que informará y reconciliará las diferencias entre dos instalaciones python administradas por pip.

¿Cómo puedo obtener mediante progtwigción la información proporcionada por la pip list sin realizar una invocación de subprogtwig de pip?

Las respuestas principales a partir del 2/1/2019 están desactualizadas y ya no funcionan con las versiones más recientes de pip.

Pero no se preocupe, aún es posible obtener una lista de paquetes programáticamente:

Opciones:

A. _internal.main

 from pip import _internal _internal.main(['list']) 

Esto imprimirá tres columnas con el paquete. Versión y ubicación

Tenga en cuenta que no se recomienda el uso de la API interna de pip.

A. pkg_resources

 import pkg_resources print([p.project_name for p in pkg_resources.working_set]) # note that this is same as calling pip._vendor.pkg_resources.working_set 

B. iter_modules

Se tarda mucho tiempo en ejecutarse (~ 300 ms en la computadora con CPU I5, SSD y 8 gigas de memoria). El beneficio es que tendrá una lista de módulos mucho más extensa y dará nombres importantes.

Ejemplo : python-dateutil se importa como dateutil, pero iter_modules le dará el nombre importable: dateutil

 from pkgutil import iter_modules print([p.name for p in iter_modules()]) 

C. Llamar a pip en línea de comando a través de subproceso

La solución a esto es trivial y dejaré esto como un ejercicio para el lector.

También soy demasiado perezoso para hacer esto, ¡buena suerte! :RE

Actualización para Python 3.6 y Pip 19.0.1

 > from pip._internal.utils.misc import get_installed_distributions > p = get_installed_distributions() > pprint.pprint(p) [wheel 0.32.3 (/usr/local/lib/python3.7/site-packages), wcwidth 0.1.7 (/usr/local/lib/python3.7/site-packages), virtualenv 16.0.0 (/usr/local/lib/python3.7/site-packages), virtualenv-clone 0.3.0 (/usr/local/lib/python3.7/site-packages), urllib3 1.24.1 (/usr/local/lib/python3.7/site-packages), typing 3.6.6 (/usr/local/lib/python3.7/site-packages), terminaltables 3.1.0 (/usr/local/lib/python3.7/site-packages), ... 

Respuesta original

Pip es solo un módulo de Python, así que simplemente impórtalo y llama a la list :

 import pip pip.main(['list']) # you can get details on package using show: pip.main(['show', 'wheel']) 

Ok así que hay mejor manera:

 pip.utils.get_installed_distributions() 

le devuelve la lista de paquetes instalados.

 packages = pip.utils.get_installed_distributions() p = packages[0] p.project_name p.version p.egg_name p.location 

Puedes ver lo que está haciendo la pip list desde el código fuente aquí

Además, get_installed_distributions acepta una gran cantidad de parámetros para devolver solo paquetes locales (de virtualenv actual), etc. Consulte la ayuda aquí .

También hay un comando subyacente de bajo nivel del módulo _vendor :

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

Sin embargo, get_installed_distributions proporciona una API más simple.

Para completar, aquí está la pip.main() de pip.main() desarrollada con la captura de stdout. Por supuesto, usar get_installed_distributions() es la solución preferida.

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