Python и pip, перечислите все версии пакета, который доступен?
дано имя Python (2.Пакет X), который может быть установлен с Пип и virtualenv, есть ли способ узнать список всех возможных версий, что pip может установить? Сейчас это метод проб и ошибок.
Я пытаюсь установить версию для сторонней библиотеки, но новейшая версия слишком новая, были сделаны обратные несовместимые изменения. Поэтому я хотел бы как-то иметь список всех версий, о которых знает Пип, поэтому что я могу их проверить.
17 ответов
скрипт в pastebin работает. Однако это не очень удобно, если вы работаете с несколькими средами / хостами, потому что вам придется копировать/создавать его каждый раз.
лучшим универсальным решением было бы использовать желток, который доступен для установки с pip. Е. Г. чтобы увидеть, какие версии Джанго доступны:
$ pip install yolk
$ 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.
Примечание: Я не участвую в развитии желтка. если что-то не работает так, как надо, оставив комментарий здесь не должно иметь большого значения. использовать желток проблема tracker вместо этого и рассмотрите возможность отправки исправления, если это возможно.
на 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 использовать
pip install pylibmc==blork
здесь blork
может быть любая строка, которая вряд ли будет кандидатом на установку.
обновление:
по состоянию на сентябрь 2017 года этот метод больше не работает:--no-install
был удален в pip 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)
вам не нужен третий пакет, чтобы получить эту информацию. 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
вы могли бы пакет yolk3k вместо желтка. yolk3k-это вилка из исходного желтка, и она поддерживает python2 и 3.
pip install yolk3k
посмотрев на код pip некоторое время, похоже, что код, ответственный за размещение пакетов, можно найти в PackageFinder
класс pip.index
. Его метод find_requirement
ищет варианты InstallRequirement
, но, к сожалению, возвращает только последнюю версию.
приведенный ниже код является почти 1: 1 копией исходной функции, а возврат в строке 114 изменен, чтобы вернуть все версии.
сценарий ожидает одно имя пакета в качестве первого и единственного аргумента и возвращает все версии.
я не могу гарантировать правильность, так как я не знаком с кодом 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]
Я придумал dead-простой скрипт bash. Спасибо jq не'автора.
#!/bin/bash
set -e
PACKAGE_JSON_URL="https://pypi.python.org/pypi//json"
curl -s "$PACKAGE_JSON_URL" | jq -r '.releases | keys | .[]' | sort -V
обновление: добавить сортировку по номеру версии.
https://pypi.python.org/pypi/Django/ - работает для пакетов, сопровождающие которых предпочитают показывать все пакеты https://pypi.python.org/simple/pip/ - должно сработать, во всяком случае (список ссылок)
мне не повезло с 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
...
Pip 7.1.0 удалил параметр --no-install из установки. Я нашел способ получить все версии пакета без какого-либо дополнительного пакета.
$ pip install --no-deps Django==x.x.x
Collecting Django==x.x.x.
Could not find a version that satisfies the requirement Django==x.x.x. (from versions: 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.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.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1, 1.8.2)
No matching distribution found for Django==x.x.x.
это работает для меня на 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
Я знаю, что это глупо, но вы можете попробовать что-то вроде этого:
pip install django == x
это приведет к ошибке, но перечислит все версии, доступные для этого пакета.
просто заменить django
С пакетом, который вы хотите, а также я считаю, надеюсь, нет такой версии под названием x.
Я только что запустил это:
pip show packagename
например:
> pip3 show setuptools
---
Metadata-Version: 2.0
Name: setuptools
Version: 18.4
Summary: Easily download, build, install, upgrade, and uninstall Python packages
Home-page: https://bitbucket.org/pypa/setuptools
Author: Python Packaging Authority
Author-email: distutils-sig@python.org
License: PSF or ZPL
Location: /usr/local/lib/python3.4/site-packages
Requires:
вы можете использовать этот короткий фрагмент Python3, чтобы захватить список доступных версий для пакета из PyPI. В отличие от некоторых других решений Python, размещенных здесь, это не разбивается на свободные версии, такие как django
' s 1.10rc1
или uwsgi
' s 2.0.13.1
:
>>> import requests
>>> from pkg_resources import parse_version
>>>
>>> def versions(name):
... url = "https://pypi.python.org/pypi/{}/json".format(name)
... return sorted(requests.get(url).json()["releases"], key=parse_version)
...
>>> print(*reversed(versions("Django")), sep="\n")
1.10.3
1.10.2
1.10.1
1.10
1.10rc1
1.10b1
1.10a1
...
вот текущий метод на основе Python pip, поиск устаревшего API пакета PyPi:
from pip import index
import requests
finder = index.PackageFinder(
[],
['https://pypi.python.org/simple'],
session=requests.Session()
)
results = finder.find_all_candidates("package_name")
versions = [p.version for p in results]
My take-это комбинация нескольких опубликованных ответов с некоторыми изменениями, чтобы упростить их использование в среде python.
идея состоит в том, чтобы предоставить совершенно новую команду (смоделированную после команды install), которая дает вам экземпляр Package finder для использования. Преимущество заключается в том, что он работает и использует любые индексы, которые pip поддерживает и читает ваши локальные файлы конфигурации pip, поэтому вы получаете правильные результаты, как и с обычным pip установить.
Я сделал попытку сделать его совместимым с обоими pip v 9.x и 10.икс.. но пробовал только на 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
вы можете grep результат вашего pip list
-> % pip list | grep 'beautifulsoup4'
beautifulsoup4 (4.4.1)