Python и pip, список всех версий пакета, который доступен?

445

Учитывая имя пакета Python, который можно установить с помощью pip , есть ли способ узнать список всех возможных версий, которые может установить pip? Прямо сейчас это метод проб и ошибок.

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

Рори
источник
1
Принятый ответ не эквивалентен другому ответу со сценарием, поскольку они не генерируют одинаковый вывод.
oligofren
17
Пожалуйста, обновите выбранный ответ. Желток сломан и не нужен. Ответ с pip install pylibmc==идеальным.
Джонатан
Пожалуйста, обновите принятый ответ, как предлагает @Jonathan. Я бы не назвал его идеальным, потому что он не будет работать на более ранних версиях pip (v7 или v8), но в остальном отлично.
Энтони Хэтчкинс
1
@ Рори, пожалуйста, обнови принятый ответ, желток мертв. Ответ Криса Монтанаро - лучший метод ИМО.
Райан Фишер
1
@Rory Пожалуйста, измените принятый ответ в интересах будущих посетителей на этот популярный вопрос. Проект «Желток» больше не поддерживается, и он просто не работает, как утверждает этот ответ.
Вим

Ответы:

167

(обновление: по состоянию на март 2020 года многие люди сообщали, что установленный с помощью желтка pip install yolk3kвозвращает только последнюю версию. Ответ Криса, похоже, получил наибольшее количество голосов и работал для меня)

Скрипт на pastebin работает. Однако это не очень удобно, если вы работаете с несколькими средами / хостами, потому что вам придется копировать / создавать его каждый раз.

Лучшим универсальным решением было бы использовать yolk3k , который можно установить с помощью pip. Например, чтобы увидеть, какие версии Django доступны:

$ pip install yolk3k
$ yolk -V django
Django 1.3
Django 1.2.5
Django 1.2.4
Django 1.2.3
Django 1.2.2
Django 1.2.1
Django 1.2
Django 1.1.4
Django 1.1.3
Django 1.1.2
Django 1.0.4

yolk3kэто форк оригинала, yolkкоторый прекратил разработку в 2012 году . Хотя yolkбольше не поддерживается (как указано в комментариях ниже), yolk3kпохоже, поддерживает Python 3 и поддерживает его.

Примечание: я не участвую в разработке yolk3k. Если что-то работает не так, как надо, оставленный здесь комментарий не должен иметь большого значения. Вместо этого используйте средство отслеживания ошибок yolk3k и рассмотрите возможность отправки исправления, если это возможно.

M000
источник
4
Ответ ниже (с использованием скрипта от pastebin) более громоздкий, но, по крайней мере, работает в моем случае (поиск версий scipy). Желток показывает только последнюю доступную версию, другой скрипт показывает все версии, начиная с 0.8.0.
oligofren
31
Большую часть времени он вернет только новейшую версию
PawelRoman
17
Ель python3 просто используйте pip install yolk3k. Команда желток будет доступна.
Пьер Криуланси
9
Как и желток, в большинстве случаев yolk3k возвращает только самую новую версию.
Diabloneo
4
желток сломан / больше не поддерживается. удалите этот ответ.
Вим
840

Для пипса> = 9.0 используйте

$ pip install pylibmc==
Collecting pylibmc==
  Could not find a version that satisfies the requirement pylibmc== (from 
  versions: 0.2, 0.3, 0.4, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5, 0.6.1, 0.6, 
  0.7.1, 0.7.2, 0.7.3, 0.7.4, 0.7, 0.8.1, 0.8.2, 0.8, 0.9.1, 0.9.2, 0.9, 
  1.0-alpha, 1.0-beta, 1.0, 1.1.1, 1.1, 1.2.0, 1.2.1, 1.2.2, 1.2.3, 1.3.0)
No matching distribution found for pylibmc==

- все доступные версии будут распечатаны без фактической загрузки или установки каких-либо дополнительных пакетов.

Для пипса <9.0 используйте

pip install pylibmc==blork

где blorkможет быть любая строка, которая не является допустимым номером версии .

Крис Монтанаро
источник
25
Я нахожу странным, что ошибка Пипа выплевывает все версии, но у них нет аргументов, чтобы явно получить эти данные
Крис Монтанаро
2
Еще одним приятным свойством этого решения является то, что оно работает со всеми обычными флагами для ограничения источников установки. Например, pip install --only-binary :all: pylibmcбудут перечислены все версии pylibmc, доступные в виде бинарных пакетов.
павон
3
pip install pylibmc==9999999 | tr ', ' "\n" | sort -n
Викас
18
Это должно быть помечено как правильный ответ, поскольку не требует установки каких-либо других пакетов.
Ив Дорфсман
5
Немного смешно, что это единственный способ сделать это в пипсах. Я надеюсь, что есть хотя бы открытый вопрос об этом на их баг-трекере?
pmos
69

Обновление: по
состоянию на сентябрь 2017 г. этот метод больше не работает: --no-installбыл удален в пипе 7

Используйте pip install -v, вы можете увидеть все версии, которые доступны

root@node7:~# pip install web.py -v
Downloading/unpacking web.py
  Using version 0.37 (newest of versions: 0.37, 0.36, 0.35, 0.34, 0.33, 0.33, 0.32, 0.31, 0.22, 0.2)
  Downloading web.py-0.37.tar.gz (90Kb): 90Kb downloaded
  Running setup.py egg_info for package web.py
    running egg_info
    creating pip-egg-info/web.py.egg-info

Чтобы не устанавливать какой-либо пакет, используйте одно из следующих решений:

root@node7:~# pip install --no-deps --no-install flask -v                                                                                                      
Downloading/unpacking flask
  Using version 0.10.1 (newest of versions: 0.10.1, 0.10, 0.9, 0.8.1, 0.8, 0.7.2, 0.7.1, 0.7, 0.6.1, 0.6, 0.5.2, 0.5.1, 0.5, 0.4, 0.3.1, 0.3, 0.2, 0.1)
  Downloading Flask-0.10.1.tar.gz (544Kb): 544Kb downloaded

или

root@node7:~# cd $(mktemp -d)
root@node7:/tmp/tmp.c6H99cWD0g# pip install flask -d . -v
Downloading/unpacking flask
  Using version 0.10.1 (newest of versions: 0.10.1, 0.10, 0.9, 0.8.1, 0.8, 0.7.2, 0.7.1, 0.7, 0.6.1, 0.6, 0.5.2, 0.5.1, 0.5, 0.4, 0.3.1, 0.3, 0.2, 0.1)
  Downloading Flask-0.10.1.tar.gz (544Kb): 4.1Kb downloaded

Протестировано с пипом 1.0

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
HVNSweeting
источник
9
pip 1.5.4дает DEPRECATION: --no-install, --no-download, --build, and --no-clean are deprecated. See https://github.com/pypa/pip/issues/906.и не показывает доступные версии для пакетов, которые уже установлены.
int_ua
2
чтобы показать все версии, это просто необходимо -v. Остальная часть моего ответа - чтобы избежать эффекта сложения (установка / загрузка). Для установленного pkg просто добавьте --upgrade. Anw, вы можете создать отдельный virtualenv, чтобы сделать все проще.
HVNSweeting
2
пип 9.0.1 лает:no such option: --no-install
tired_of_nitpickers
«новейшая из версий:» из -v исключает некоторые версии.
mmacvicar
56

Вам не нужен сторонний пакет для получения этой информации. Pypi предоставляет простые потоки JSON для всех пакетов в

https://pypi.python.org/pypi/{PKG_NAME}/json

Вот некоторый код Python, использующий только стандартную библиотеку, которая получает все версии.

import json
import urllib2
from distutils.version import StrictVersion

def versions(package_name):
    url = "https://pypi.python.org/pypi/%s/json" % (package_name,)
    data = json.load(urllib2.urlopen(urllib2.Request(url)))
    versions = data["releases"].keys()
    versions.sort(key=StrictVersion)
    return versions

print "\n".join(versions("scikit-image"))

Код напечатан (по состоянию на 23 февраля 2015 г.):

0.7.2
0.8.0
0.8.1
0.8.2
0.9.0
0.9.1
0.9.2
0.9.3
0.10.0
0.10.1
Эрик Чианг
источник
2
JSON имеет достаточное количество вложений. Раньше я versions = [x for x in data["releases"] if any([y["python_version"] in ['cp26', '2.6'] for y in data["releases"][x]])]находил версии, совместимые с Python 2.6. (Я нигде не видел cp26, но некоторые пакеты были, cp27поэтому я предполагаю, что это может существовать в других пакетах.)
tripleee
2
Вот способ сделать это с помощью curl, jq и sort («однострочник»!): curl -s https://pypi.python.org/pypi/{PKG_NAME}/json | jq -r '.releases | keys[]' | sort -t. -k 1,1n -k 2,2n -k 3,3n
Алан Айви,
1
Это создает ValueErrorисключение для некоторых пакетов, которые следуют не очень строгим схемам управления версиями. Чтобы исправить это для этих пакетов, посмотрите эту суть .
TrinitronX
устаревший сделает это за вас.
Шади
18

Я придумал простой сценарий bash. Спасибо автору jq .

#!/bin/bash
set -e

PACKAGE_JSON_URL="https://pypi.org/pypi/${1}/json"

curl -s "$PACKAGE_JSON_URL" | jq  -r '.releases | keys | .[]' | sort -V

Обновление: добавить сортировку по номеру версии.

Тимофей Столбов
источник
Я не смог добраться curlдо работы, возможно, из-за ошибок сертификата. wget --no-check-certificateработает, но даже curl -k --insecureничего не выдает. Предупреждение я с wgetговоритERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
tripleee
sort -VНе работает на OSX с версией доморощенного оjq
deepelement
16

Вы могли бы пакет yolk3k вместо желтка. yolk3k - это форк из оригинального желтка, и он поддерживает как python2, так и 3.

https://github.com/myint/yolk

pip install yolk3k
ykyuen
источник
Это было удобно знать, так как желток не работает под python 3.x
Broken Man
1
yolk3k возвращает только установленную для меня версию:yolk -V attest Attest 0.5.3
Энтони Хэтчкинс
2
yolk3k, похоже, возвращает только последнюю версию?
mvherweg
16

Посмотрев некоторое время на код pip, похоже, что код, отвечающий за поиск пакетов, можно найти в PackageFinderклассе в pip.index. Его метод find_requirementищет версииInstallRequirement , но, к сожалению, возвращает только самую последнюю версию.

Приведенный ниже код является почти 1: 1 копией оригинальной функции, при этом возвращаемая строка в строке 114 изменена для возврата всех версий.

Сценарий ожидает одно имя пакета в качестве первого и единственного аргумента и возвращает все версии.

http://pastebin.com/axzdUQhZ

Я не могу гарантировать правильность, так как я не знаком с кодом pip. Но, надеюсь, это поможет.

Образец вывода

python test.py pip
Versions of pip
0.8.2
0.8.1
0.8
0.7.2
0.7.1
0.7
0.6.3
0.6.2
0.6.1
0.6
0.5.1
0.5
0.4
0.3.1
0.3
0.2.1
0.2 dev

Код:

import posixpath
import pkg_resources
import sys
from pip.download import url_to_path
from pip.exceptions import DistributionNotFound
from pip.index import PackageFinder, Link
from pip.log import logger
from pip.req import InstallRequirement
from pip.util import Inf


class MyPackageFinder(PackageFinder):

    def find_requirement(self, req, upgrade):
        url_name = req.url_name
        # Only check main index if index URL is given:
        main_index_url = None
        if self.index_urls:
            # Check that we have the url_name correctly spelled:
            main_index_url = Link(posixpath.join(self.index_urls[0], url_name))
            # This will also cache the page, so it's okay that we get it again later:
            page = self._get_page(main_index_url, req)
            if page is None:
                url_name = self._find_url_name(Link(self.index_urls[0]), url_name, req) or req.url_name

        # Combine index URLs with mirror URLs here to allow
        # adding more index URLs from requirements files
        all_index_urls = self.index_urls + self.mirror_urls

        def mkurl_pypi_url(url):
            loc = posixpath.join(url, url_name)
            # For maximum compatibility with easy_install, ensure the path
            # ends in a trailing slash.  Although this isn't in the spec
            # (and PyPI can handle it without the slash) some other index
            # implementations might break if they relied on easy_install's behavior.
            if not loc.endswith('/'):
                loc = loc + '/'
            return loc
        if url_name is not None:
            locations = [
                mkurl_pypi_url(url)
                for url in all_index_urls] + self.find_links
        else:
            locations = list(self.find_links)
        locations.extend(self.dependency_links)
        for version in req.absolute_versions:
            if url_name is not None and main_index_url is not None:
                locations = [
                    posixpath.join(main_index_url.url, version)] + locations

        file_locations, url_locations = self._sort_locations(locations)

        locations = [Link(url) for url in url_locations]
        logger.debug('URLs to search for versions for %s:' % req)
        for location in locations:
            logger.debug('* %s' % location)
        found_versions = []
        found_versions.extend(
            self._package_versions(
                [Link(url, '-f') for url in self.find_links], req.name.lower()))
        page_versions = []
        for page in self._get_pages(locations, req):
            logger.debug('Analyzing links from page %s' % page.url)
            logger.indent += 2
            try:
                page_versions.extend(self._package_versions(page.links, req.name.lower()))
            finally:
                logger.indent -= 2
        dependency_versions = list(self._package_versions(
            [Link(url) for url in self.dependency_links], req.name.lower()))
        if dependency_versions:
            logger.info('dependency_links found: %s' % ', '.join([link.url for parsed, link, version in dependency_versions]))
        file_versions = list(self._package_versions(
                [Link(url) for url in file_locations], req.name.lower()))
        if not found_versions and not page_versions and not dependency_versions and not file_versions:
            logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
            raise DistributionNotFound('No distributions at all found for %s' % req)
        if req.satisfied_by is not None:
            found_versions.append((req.satisfied_by.parsed_version, Inf, req.satisfied_by.version))
        if file_versions:
            file_versions.sort(reverse=True)
            logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions]))
            found_versions = file_versions + found_versions
        all_versions = found_versions + page_versions + dependency_versions
        applicable_versions = []
        for (parsed_version, link, version) in all_versions:
            if version not in req.req:
                logger.info("Ignoring link %s, version %s doesn't match %s"
                            % (link, version, ','.join([''.join(s) for s in req.req.specs])))
                continue
            applicable_versions.append((link, version))
        applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True)
        existing_applicable = bool([link for link, version in applicable_versions if link is Inf])
        if not upgrade and existing_applicable:
            if applicable_versions[0][1] is Inf:
                logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
                            % req.satisfied_by.version)
            else:
                logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)'
                            % (req.satisfied_by.version, applicable_versions[0][1]))
            return None
        if not applicable_versions:
            logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)'
                         % (req, ', '.join([version for parsed_version, link, version in found_versions])))
            raise DistributionNotFound('No distributions matching the version for %s' % req)
        if applicable_versions[0][0] is Inf:
            # We have an existing version, and its the best version
            logger.info('Installed version (%s) is most up-to-date (past versions: %s)'
                        % (req.satisfied_by.version, ', '.join([version for link, version in applicable_versions[1:]]) or 'none'))
            return None
        if len(applicable_versions) > 1:
            logger.info('Using version %s (newest of versions: %s)' %
                        (applicable_versions[0][1], ', '.join([version for link, version in applicable_versions])))
        return applicable_versions


if __name__ == '__main__':
    req = InstallRequirement.from_line(sys.argv[1], None)
    finder = MyPackageFinder([], ['http://pypi.python.org/simple/'])
    versions = finder.find_requirement(req, False)
    print 'Versions of %s' % sys.argv[1]
    for v in versions:
        print v[1]
Райнер Гереке
источник
Это сработало намного лучше, чем ответ выше. тощий $ yolk -V scipy scipy 0.12.0 тощий $ python test.py scipy Версии scipy 0.12.0 0.12.0 0.11.0 0.11.0 0.10.1 0.10.1 0.10.0 0.10.0 0.9.0 0.9.0 0.8.0
oligofren
1
Такое использование явно не рекомендуется в документах : « вы не должны использовать внутренние API pip таким способом »
wim
9

Вы можете использовать этот небольшой скрипт Python 3 (используя только стандартные библиотечные модули), чтобы получить список доступных версий для пакета из PyPI с помощью JSON API и распечатать их в обратном хронологическом порядке. В отличие от некоторых других решений Python, опубликованных здесь, это не нарушает свободные версии, такие как django's ' 2.2rc1или uwsgi's' 2.0.17.1:

#!/usr/bin/env python3

import json
import sys
from urllib import request    
from pkg_resources import parse_version    

def versions(pkg_name):
    url = f'https://pypi.python.org/pypi/{pkg_name}/json'
    releases = json.loads(request.urlopen(url).read())['releases']
    return sorted(releases, key=parse_version, reverse=True)    

if __name__ == '__main__':
    print(*versions(sys.argv[1]), sep='\n')

Сохраните скрипт и запустите его с именем пакета в качестве аргумента, например:

python versions.py django
3.0a1
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2
2.2rc1
...
Евгений Ярмаш
источник
7

Это работает для меня на OSX:

pip install docker-compose== 2>&1 \
| grep -oE '(\(.*\))' \
| awk -F:\  '{print$NF}' \
| sed -E 's/( |\))//g' \
| tr ',' '\n'

Возвращает список по одному в строке:

1.1.0rc1
1.1.0rc2
1.1.0
1.2.0rc1
1.2.0rc2
1.2.0rc3
1.2.0rc4
1.2.0
1.3.0rc1
1.3.0rc2
1.3.0rc3
1.3.0
1.3.1
1.3.2
1.3.3
1.4.0rc1
1.4.0rc2
1.4.0rc3
1.4.0
1.4.1
1.4.2
1.5.0rc1
1.5.0rc2
1.5.0rc3
1.5.0
1.5.1
1.5.2
1.6.0rc1
1.6.0
1.6.1
1.6.2
1.7.0rc1
1.7.0rc2
1.7.0
1.7.1
1.8.0rc1
1.8.0rc2
1.8.0
1.8.1
1.9.0rc1
1.9.0rc2
1.9.0rc3
1.9.0rc4
1.9.0
1.10.0rc1
1.10.0rc2
1.10.0

Или получить последнюю доступную версию:

pip install docker-compose== 2>&1 \
| grep -oE '(\(.*\))' \
| awk -F:\  '{print$NF}' \
| sed -E 's/( |\))//g' \
| tr ',' '\n' \
| gsort -r -V \
| head -1
1.10.0rc2

Имейте в виду, gsortдолжен быть установлен (на OSX) для анализа версий. Вы можете установить его сbrew install coreutils

бабушка
источник
Боже, почему ты даже опубликовал этот ответ? @ Крис Монтаро ответ работает и элегантно. Это просто излишне вводит осложнения
Брайан Лич
@BrianLeach smh ... такой же подход отфильтрован для использования в сценарии ...
бабушка
1
У меня работает в cygwin / bash, для второго решения используйте sort, а не gsort в cygwin.
WebComer
Здесь python дает, пожалуй, более читаемый код, чем bash ... см. Ответ @eric chiang (надеюсь :) выше ...
mirekphd
4

Мой проект ludditeимеет эту функцию.

Пример использования:

>>> import luddite
>>> luddite.get_versions_pypi("python-dateutil")
('0.1', '0.3', '0.4', '0.5', '1.0', '1.1', '1.2', '1.4', '1.4.1', '1.5', '2.0', '2.1', '2.2', '2.3', '2.4.0', '2.4.1', '2.4.2', '2.5.0', '2.5.1', '2.5.2', '2.5.3', '2.6.0', '2.6.1', '2.7.0', '2.7.1', '2.7.2', '2.7.3', '2.7.4', '2.7.5', '2.8.0')

В нем перечислены все доступные версии пакета, запросив API-интерфейс json по адресу https://pypi.org/.

Wim
источник
Было бы более поучительно, если бы вы сказали нам, что делает ваш пакет, иначе вы просто продвигаете свое программное обеспечение :)
user228395
@ user228395 Я подумал, что это достаточно очевидно, но в нем перечислены все доступные версии пакета, о чем и спрашивает заголовок вопроса. Отредактировано - лучше?
Вим
Его работа, конечно. Так что же, по сути, оборачивает решение, представленное @Timofey Stolbov?
user228395
1
@ user228395 Я бы не назвал это «переносом», поскольку в этом ответе используются bash, curl и jq - тогда как luddite просто использует стандартную библиотеку Python (urllib). Но решение от Столбова использует ту же конечную точку на pypi.org . Могу ли я спросить, в чем причина вашего отрицательного голоса?
Вим
1
Если вы перейдете по ссылке на страницу сведений о проекте, то увидите, что основная функция проекта - проверка requirements.txtфайлов на устаревшие пакеты. Это больше, чем пара строк кода. Чтобы проверить requirements.txtфайл, вам нужна функциональность для перечисления всех версий пакета. Эта часть намеренно отделена и является частью публичного API luddite. И это исходная Apache License 2.0, я думаю, что это не совсем справедливо называть «программным пакетом черного ящика».
Вим
2

У меня не было никакой удачи с yolk, yolk3kили , pip install -vно так что я в конечном итоге с помощью этого (адаптировано к Python 3 из ответа Эриком Чанга):

import json
import requests
from distutils.version import StrictVersion

def versions(package_name):
    url = "https://pypi.python.org/pypi/{}/json".format(package_name)
    data = requests.get(url).json()
    return sorted(list(data["releases"].keys()), key=StrictVersion, reverse=True)

>>> print("\n".join(versions("gunicorn")))
19.1.1
19.1.0
19.0.0
18.0
17.5
0.17.4
0.17.3
...
Эндрю Маги
источник
1
StrictVersionне будет работать для многих пакетов ( django, uwsgi, psycopg2чтобы назвать несколько). Вы можете использовать parse_version()от setuptools(см. Мой ответ для примера).
Евгений Ярмаш
1

Альтернативное решение - использовать API хранилища:

https://warehouse.readthedocs.io/api-reference/json/#release

Например, для колбы:

import requests
r = requests.get("https://pypi.org/pypi/Flask/json")
print(r.json()['releases'].keys())

напечатает:

dict_keys(['0.1', '0.10', '0.10.1', '0.11', '0.11.1', '0.12', '0.12.1', '0.12.2', '0.12.3', '0.12.4', '0.2', '0.3', '0.3.1', '0.4', '0.5', '0.5.1', '0.5.2', '0.6', '0.6.1', '0.7', '0.7.1', '0.7.2', '0.8', '0.8.1', '0.9', '1.0', '1.0.1', '1.0.2'])
Чарли
источник
0

Простой bashскрипт, который полагается только на pythonсебя (я предполагаю, что в контексте вопроса он должен быть установлен) и один из curlили wget. Предполагается, что у вас установлен setuptoolsпакет для сортировки версий (почти всегда установлен). Он не зависит от внешних зависимостей, таких как:

  • jq который может не присутствовать;
  • grepи awkэто может вести себя по-разному в Linux и macOS.
curl --silent --location https://pypi.org/pypi/requests/json | python -c "import sys, json, pkg_resources; releases = json.load(sys.stdin)['releases']; print(' '.join(sorted(releases, key=pkg_resources.parse_version)))"

Чуть более длинная версия с комментариями.

Поместите имя пакета в переменную:

PACKAGE=requests

Получить версии (используя curl):

VERSIONS=$(curl --silent --location https://pypi.org/pypi/$PACKAGE/json | python -c "import sys, json, pkg_resources; releases = json.load(sys.stdin)['releases']; print(' '.join(sorted(releases, key=pkg_resources.parse_version)))")

Получить версии (используя wget):

VERSIONS=$(wget -qO- https://pypi.org/pypi/$PACKAGE/json | python -c "import sys, json, pkg_resources; releases = json.load(sys.stdin)['releases']; print(' '.join(sorted(releases, key=pkg_resources.parse_version)))")

Распечатать отсортированные версии:

echo $VERSIONS
Андрей Семакин
источник
-1

Мое мнение - это комбинация нескольких опубликованных ответов с некоторыми изменениями, облегчающими их использование в работающей среде Python.

Идея состоит в том, чтобы предоставить совершенно новую команду (смоделированную после команды установки), которая дает вам экземпляр искателя пакетов для использования. Положительным моментом является то, что он работает и использует любые индексы, которые поддерживает pip, и читает ваши локальные файлы конфигурации pip, поэтому вы получите правильные результаты, как при обычной установке pip.

Я попытался сделать его совместимым как с pip v 9.x, так и с 10.x .., но попробовал только на 9.x

https://gist.github.com/kaos/68511bd013fcdebe766c981f50b473d4

#!/usr/bin/env python
# When you want a easy way to get at all (or the latest) version of a certain python package from a PyPi index.

import sys
import logging

try:
    from pip._internal import cmdoptions, main
    from pip._internal.commands import commands_dict
    from pip._internal.basecommand import RequirementCommand
except ImportError:
    from pip import cmdoptions, main
    from pip.commands import commands_dict
    from pip.basecommand import RequirementCommand

from pip._vendor.packaging.version import parse as parse_version

logger = logging.getLogger('pip')

class ListPkgVersionsCommand(RequirementCommand):
    """
    List all available versions for a given package from:

    - PyPI (and other indexes) using requirement specifiers.
    - VCS project urls.
    - Local project directories.
    - Local or remote source archives.

    """
    name = "list-pkg-versions"
    usage = """
      %prog [options] <requirement specifier> [package-index-options] ...
      %prog [options] [-e] <vcs project url> ...
      %prog [options] [-e] <local project path> ...
      %prog [options] <archive url/path> ..."""

    summary = 'List package versions.'

    def __init__(self, *args, **kw):
        super(ListPkgVersionsCommand, self).__init__(*args, **kw)

        cmd_opts = self.cmd_opts

        cmd_opts.add_option(cmdoptions.install_options())
        cmd_opts.add_option(cmdoptions.global_options())
        cmd_opts.add_option(cmdoptions.use_wheel())
        cmd_opts.add_option(cmdoptions.no_use_wheel())
        cmd_opts.add_option(cmdoptions.no_binary())
        cmd_opts.add_option(cmdoptions.only_binary())
        cmd_opts.add_option(cmdoptions.pre())
        cmd_opts.add_option(cmdoptions.require_hashes())

        index_opts = cmdoptions.make_option_group(
            cmdoptions.index_group,
            self.parser,
        )

        self.parser.insert_option_group(0, index_opts)
        self.parser.insert_option_group(0, cmd_opts)

    def run(self, options, args):
        cmdoptions.resolve_wheel_no_use_binary(options)
        cmdoptions.check_install_build_global(options)

        with self._build_session(options) as session:
            finder = self._build_package_finder(options, session)

            # do what you please with the finder object here... ;)
            for pkg in args:
                logger.info(
                    '%s: %s', pkg,
                    ', '.join(
                        sorted(
                            set(str(c.version) for c in finder.find_all_candidates(pkg)),
                            key=parse_version,
                        )
                    )
                )


commands_dict[ListPkgVersionsCommand.name] = ListPkgVersionsCommand

if __name__ == '__main__':
    sys.exit(main())

Пример вывода

./list-pkg-versions.py list-pkg-versions pika django
pika: 0.5, 0.5.1, 0.5.2, 0.9.1a0, 0.9.2a0, 0.9.3, 0.9.4, 0.9.5, 0.9.6, 0.9.7, 0.9.8, 0.9.9, 0.9.10, 0.9.11, 0.9.12, 0.9.13, 0.9.14, 0.10.0b1, 0.10.0b2, 0.10.0, 0.11.0b1, 0.11.0, 0.11.1, 0.11.2, 0.12.0b2
django: 1.1.3, 1.1.4, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.4.10, 1.4.11, 1.4.12, 1.4.13, 1.4.14, 1.4.15, 1.4.16, 1.4.17, 1.4.18, 1.4.19, 1.4.20, 1.4.21, 1.4.22, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11, 1.5.12, 1.6, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.6.11, 1.7, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10, 1.7.11, 1.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.8.5, 1.8.6, 1.8.7, 1.8.8, 1.8.9, 1.8.10, 1.8.11, 1.8.12, 1.8.13, 1.8.14, 1.8.15, 1.8.16, 1.8.17, 1.8.18, 1.8.19, 1.9a1, 1.9b1, 1.9rc1, 1.9rc2, 1.9, 1.9.1, 1.9.2, 1.9.3, 1.9.4, 1.9.5, 1.9.6, 1.9.7, 1.9.8, 1.9.9, 1.9.10, 1.9.11, 1.9.12, 1.9.13, 1.10a1, 1.10b1, 1.10rc1, 1.10, 1.10.1, 1.10.2, 1.10.3, 1.10.4, 1.10.5, 1.10.6, 1.10.7, 1.10.8, 1.11a1, 1.11b1, 1.11rc1, 1.11, 1.11.1, 1.11.2, 1.11.3, 1.11.4, 1.11.5, 1.11.6, 1.11.7, 1.11.8, 1.11.9, 1.11.10, 1.11.11, 1.11.12, 2.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4
Kaos
источник
такое использование явно не рекомендуется в документах : « вы не должны использовать внутренние API pip таким образом »
wim