给定可以与pip一起安装的Python包的名称,是否有任何方法可以找到pip可以安装的所有可能版本的列表?现在是反复试验。
我正在尝试为第三方库安装一个版本,但最新版本太新了,有向后不兼容的更改。因此,我希望以某种方式获得pip所知道的所有版本的列表,以便我可以测试它们。
给定可以与pip一起安装的Python包的名称,是否有任何方法可以找到pip可以安装的所有可能版本的列表?现在是反复试验。
我正在尝试为第三方库安装一个版本,但最新版本太新了,有向后不兼容的更改。因此,我希望以某种方式获得pip所知道的所有版本的列表,以便我可以测试它们。
在看了一段时间pip的代码之后,负责定位包的代码似乎可以在pip.index中的PackageFinder类中找到。它的方法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]
(更新:截至2020年3月,许多人报告说,通过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是原蛋黄的一个分支,于2012年停止开发。虽然不再维护蛋黄(如下面的评论所示),但蛋黄3k似乎是并支持Python 3。
注意:我没有参与蛋黄3k的形成。如果有些东西似乎没有像它应该的那样工作,在这里留下评论应该不会有太大的区别。如果可能的话,请使用yolk3k问题跟踪器,并考虑提交修复程序。
https://pypi.python.org/pypi/Django/—适用于那些维护者选择显示所有包的包 https://pypi.python.org/simple/pip/ -无论如何都应该做到(列出所有链接)
更新: 截至2017年9月,这种方法不再有效:——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
or
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)
你可以用3k的蛋黄来代替蛋黄。Yolk3k是最初的蛋黄的分支,它同时支持python2和3。
https://github.com/myint/yolk
pip install yolk3k
对于pip >= 21.2使用:
pip index versions pylibmc
注意,这个命令是实验性的,将来可能会改变!
对于pip >= 21.1使用:
pip install pylibmc==
对于pip >= 20.3使用:
pip install --use-deprecated=legacy-resolver pylibmc==
对于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使用:
pip install pylibmc==blork
其中,block可以是任何不是有效版本号的字符串。
您不需要第三方包来获取此信息。pypi为下的所有包提供简单的JSON提要
https://pypi.org/pypi/{PKG_NAME}/json
下面是一些仅使用标准库的Python代码,该标准库可以获得所有版本。
import json
import urllib2
from distutils.version import StrictVersion
def versions(package_name):
url = "https://pypi.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"))
该代码打印(截至2015年2月23日):
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或pip install -v的运气,但我最终使用了这个(从eric chiang的答案改编到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
...
我想出了一个非常简单的bash脚本。感谢jq的作者。
#!/bin/bash
set -e
PACKAGE_JSON_URL="https://pypi.org/pypi/${1}/json"
curl -L -s "$PACKAGE_JSON_URL" | jq -r '.releases | keys | .[]' | sort -V
更新: 添加按版本号排序的功能。 添加-L跟随重定向。
您可以使用这个小型Python 3脚本(仅使用标准库模块)使用JSON API从PyPI获取包的可用版本列表,并按时间倒序打印它们。与这里发布的其他Python解决方案不同,这不会破坏松散版本,如django的2.2rc1或uwsgi的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
...
这适用于我在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安装它
我的想法是结合了几个已经发布的答案,并做了一些修改,使它们更容易在运行的python环境中使用。
其思想是提供一个全新的命令(模仿install命令),为您提供要使用的包查找器实例。优点是它可以使用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
另一种解决方案是使用仓库api:
https://warehouse.readthedocs.io/api-reference/json/#release
例如,对于Flask:
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'])
我的项目卢德特就有这个特点。
使用示例:
>>> 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')
它通过查询https://pypi.org/的JSON API列出了一个包的所有可用版本
简单的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
您可以尝试安装不存在的软件包版本。然后pip将列出可用的版本
pip install hell==99999
ERROR: Could not find a version that satisfies the requirement hell==99999
(from versions: 0.1.0, 0.2.0, 0.2.1, 0.2.2, 0.2.3, 0.2.4, 0.3.0,
0.3.1, 0.3.2, 0.3.3, 0.3.4, 0.4.0, 0.4.1)
ERROR: No matching distribution found for hell==99999
以下是我在jq中对列表进行排序的答案(对于那些使用sort -V不可用的系统的人):
$ pythonPackage=certifi
$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r '.releases | keys_unsorted | sort_by( split(".") | map(tonumber) )'
.............
"2019.3.9",
"2019.6.16",
"2019.9.11",
"2019.11.28",
"2020.4.5",
"2020.4.5.1",
"2020.4.5.2",
"2020.6.20",
"2020.11.8"
]
获取包的最新版本号:
$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r '.releases | keys_unsorted | sort_by( split(".") | map(tonumber) )[-1]'
2020.11.8
或者更快一点:
$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r '.releases | keys_unsorted | max_by( split(".") | map(tonumber) )'
2020.11.8
或者更简单一点:):
$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r .info.version
2020.11.8
更新:
也许解决方案不再需要了,检查这个答案的注释。
原来的答案
对于20.03以上的pip版本,您可以使用旧的求解器来获得所有可用的版本:
$ pip install --use-deprecated=legacy-resolver pylibmc==
ERROR: Could not find a version that satisfies the requirement pylibmc== (from
versions: 0.2, 0.3, 0.4, 0.5, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.6, 0.6.1,
0.7, 0.7.1, 0.7.2, 0.7.3, 0.7.4, 0.8, 0.8.1, 0.8.2, 0.9, 0.9.1, 0.9.2, 1.0a0,
1.0b0, 1.0, 1.1, 1.1.1, 1.2.0, 1.2.1, 1.2.2, 1.2.3, 1.3.0, 1.4.0, 1.4.1,
1.4.2, 1.4.3, 1.5.0, 1.5.1, 1.5.2, 1.5.100.dev0, 1.6.0, 1.6.1)
ERROR: No matching distribution found for pylibmc==
适用于最新的pip版本,不需要额外的工具:
pip install pylibmc== -v 2>/dev/null | awk '/Found link/ {print $NF}' | uniq
这是Py3.9+版本的Limmy+EricChiang的解决方案。
import json
import urllib.request
from distutils.version import StrictVersion
# print PyPI versions of package
def versions(package_name):
url = "https://pypi.org/pypi/%s/json" % (package_name,)
data = json.load(urllib.request.urlopen(url))
versions = list(data["releases"])
sortfunc = lambda x: StrictVersion(x.replace('rc', 'b').translate(str.maketrans('cdefghijklmn', 'bbbbbbbbbbbb')))
versions.sort(key=sortfunc)
return versions
pypi版本包出色地完成了以下工作:
$ pip3 install pip-versions
$ pip-versions latest rsyncy
0.0.4
$ pip-versions list rsyncy
0.0.1
0.0.2
0.0.3
0.0.4
这甚至可以在Nexus (sonatype)代理后面工作!
我通常运行pip install packagename==somerandomstring。这将返回一个错误,提示无法找到满足packagename==somerandomstring要求的版本,与此错误一起,pip还将列出服务器上可用的版本。
e.g.
$ pip install flask==aksjflashd
Collecting flask==aksjflashd
Could not find a version that satisfies the requirement flask==aksjflashd
(from versions: 0.1, 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, 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.12.5, 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.1.0, 1.1.1, 1.1.2)
No matching distribution found for flask==aksjflashd
$
如果像'aksjflashd'这样的随机字符串被证明是实际的包版本,你必须非常不幸!
当然,您也可以在pip download中使用这个技巧。
pypi-has() { set -o pipefail; curl -sfL https://pypi.org/pypi/$1/json | jq -e --arg v $2 'any( .releases | keys[]; . == $v )'; }
用法:
$ pypi-has django 4.0x ; echo $?
false
1
$ pypi-has djangos 4.0x ; echo $?
22
$ pypi-has djangos 4.0 ; echo $?
22
$ pypi-has django 4.0 ; echo $?
true
0
使用pip install <package_name>==为Chris的答案提供编程方法
import re
import subprocess
from packaging.version import VERSION_PATTERN as _VRESION_PATTERN
VERSION_PATTERN = re.compile(_VRESION_PATTERN , re.VERBOSE | re.IGNORECASE)
def get_available_versions(package_name):
process = subprocess.run(['pip', 'install', f'{package_name}=='], stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
versions = []
for line in process.stderr.decode('utf-8').splitlines():
if 'Could not find a version that satisfies the requirement' in line:
for match in VERSION_PATTERN.finditer(line.split('from versions:')[1]):
versions.append(match.group(0))
return versions
它可以像这样使用
>>> get_available_versions('tensorflow')
['2.2.0rc1', '2.2.0rc2', '2.2.0rc3', '2.2.0rc4', '2.2.0', '2.2.1', '2.2.2', '2.2.3', '2.3.0rc0', '2.3.0rc1', '2.3.0rc2', '2.3.0', '2.3.1', '2.3.2', '2.3.3', '2.3.4', '2.4.0rc0', '2.4.0rc1', '2.4.0rc2', '2.4.0rc3', '2.4.0rc4', '2.4.0', '2.4.1', '2.4.2', '2.4.3', '2.4.4', '2.5.0rc0', '2.5.0rc1', '2.5.0rc2', '2.5.0rc3', '2.5.0', '2.5.1', '2.5.2', '2.5.3', '2.6.0rc0', '2.6.0rc1', '2.6.0rc2', '2.6.0', '2.6.1', '2.6.2', '2.6.3', '2.7.0rc0', '2.7.0rc1', '2.7.0', '2.7.1', '2.8.0rc0', '2.8.0rc1', '2.8.0']
并返回一个版本列表。
注意:它似乎提供兼容版本,而不是所有版本。要获得完整的列表,请使用Eric的json方法。
要获取GitLab私有包的最新版本,可以使用以下方法。
pip index versions package-name --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.com/api/v4/projects/<project-id>/packages/pypi/simple/ | grep 'LATEST:' | sed -E 's/LATEST:| //g'
据我所知,发布键将在不久的将来被删除,因此使用GET“https://pypi.python.org/pypi/{package_name}/json”的解决方案将不再有效。
要找到所有可用的(甚至不兼容的)版本,使用pip >= 21.x的-vv标志。
pip install sklearn== --dry-run -vv
不兼容的版本将在日志中如下所示:
Skipping link: none of the wheel's tags (cp27-cp27m-win32) are compatible