Python и pip, список всех версий пакета, который доступен? - PullRequest
342 голосов
/ 03 февраля 2011

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

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

Ответы [ 18 ]

628 голосов
/ 31 октября 2014

Для pip> = 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==

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

Для pip <9.0 </strong> use

pip install pylibmc==blork

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

152 голосов
/ 24 марта 2011

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

Лучшим универсальным решением было бы использование желток , который доступен для установки с помощью 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

Небольшое предостережение: желток зависит от распределения. Это не плохо, но это может быть проблемой, если вам по какой-то причине нужно придерживаться (устаревших) python setuptools.

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

70 голосов
/ 14 октября 2013

Обновление:
По состоянию на сентябрь 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

Протестировано с pip 1.0

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
48 голосов
/ 02 декабря 2014

Вам не нужен сторонний пакет для получения этой информации. 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
18 голосов
/ 11 августа 2014

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

https://github.com/myint/yolk

pip install yolk3k
15 голосов
/ 12 июля 2015

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

#!/bin/bash
set -e

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

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

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

15 голосов
/ 04 февраля 2011

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

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

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

http://pastebin.com/axzdUQhZ

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

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

$ 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]
11 голосов
/ 25 июля 2017

Я знаю, что это глупо, но вы можете попробовать что-то вроде этого:

pip install django==x

Это приведет к ошибке, но перечислит все версии, доступные для этого пакета.

Примечание 1: Просто замените django на нужный вам пакет.

Примечание 2: Я полагаю, что, надеюсь, не существует такой версии с именем x (используйте другую строку, еслиx соответствует реальному номеру версии).

Примечание 3: пробелов до и после ==.

нет.
8 голосов
/ 11 марта 2013

https://pypi.python.org/pypi/Django/ - работает для пакетов, сопровождающие которых хотят показать все пакеты https://pypi.python.org/simple/pip/ - в любом случае следует добиться цели (перечисляет все ссылки)

3 голосов
/ 29 января 2017

Это работает для меня на 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

...