Python: программно работающий "список пипсов"

Я пишу небольшой код, который будет сообщать и согласовывать различия между двумя установками Python, управляемыми pip.

Как программно получить информацию, предоставленную pip list без вызова подпрограммы из пипса?

Ответ 1

Лучшие ответы на 01.02.2009 устарели и больше не работают с более новыми версиями pip.

Но не стоит беспокоиться - все равно можно получить список пакетов программно:

Опции:

A. _internal.main

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

Это распечатает три столбца с пакетом. Версия и местоположение

Обратите внимание, что использование pip внутреннего API не рекомендуется.

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

Требуется много времени для выполнения (~ 300 мс на компьютере с процессором I5, SSD и 8 гигабайтами оперативной памяти). Преимущество состоит в том, что у него будет гораздо более обширный список модулей, и он будет выводить импортируемые имена.

Пример: python-dateutil импортируется как dateutil, но iter_modules даст вам импортируемое имя: dateutil

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

C. Вызовите pip в командной строке через подпроцесс

Решение этого тривиально, и я оставлю это в качестве упражнения для читателя

ака мне лень это делать, удачи! : D

Ответ 2

Обновление для Python 3.6 и 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),
 ...

Оригинальный ответ

Pip - это просто модуль Python, поэтому просто импортируйте его и вызовите list:

import pip

pip.main(['list'])

# you can get details on package using show:

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

Итак, есть лучший способ:

pip.utils.get_installed_distributions()

возвращает вам список установленных пакетов.

packages = pip.utils.get_installed_distributions()

p = packages[0]

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

Вы можете увидеть, что pip list делает из исходного кода здесь

Также get_installed_distributions принимает целую кучу параметров, чтобы возвращать только локальные пакеты (из текущего virtualenv) и т.д. Пожалуйста, смотрите помощь здесь.

Существует также базовая команда низкого уровня из модуля _vendor:

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

Однако get_installed_distributions обеспечивают более get_installed_distributions API.

Ответ 3

Для полноты здесь идея vittore pip.main() сфокусирована на захвате stdout. Конечно, использование get_installed_distributions() является предпочтительным решением.

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

Ответ 4

Используйте модуль OS или системный модуль

import os 
import subprocess as su
os.system("pip list")
su.call(["pip","list"])