Python 和 pip,列出可用包的所有版本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4888027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python and pip, list all versions of a package that's available?
提问by Rory
Given the name of a Python package that can be installed with pip, is there any way to find out a list of all the possible versions of it that pip could install? Right now it's trial and error.
鉴于可以使用pip安装的 Python 包的名称,有没有办法找出 pip 可以安装的所有可能版本的列表?现在是反复试验。
I'm trying to install a version for a third party library, but the newest version is too new, there were backwards incompatible changes made. So I'd like to somehow have a list of all the versions that pip knows about, so that I can test them.
我正在尝试为第三方库安装一个版本,但最新版本太新,进行了向后不兼容的更改。所以我想以某种方式列出 pip 知道的所有版本,以便我可以测试它们。
采纳答案by m000
(update: As of March 2020, many people have reported that yolk, installed via pip install yolk3k, only returns latest version. Chris's answerseems to have the most upvotes and worked for me)
(更新:截至 2020 年 3 月,许多人报告说,通过 安装的 yolkpip install yolk3k仅返回最新版本 。Chris 的回答似乎获得了最多的赞成票并且对我有用)
The script at pastebin does work. However it's not very convenient if you're working with multiple environments/hosts because you will have to copy/create it every time.
pastebin 的脚本确实有效。但是,如果您使用多个环境/主机,这不是很方便,因为您每次都必须复制/创建它。
A better all-around solution would be to use yolk3k, which is available to install with pip. E.g. to see what versions of Django are available:
更好的全方位解决方案是使用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
yolk3kis a fork of the original yolkwhich ceased development in 2012. Though yolkis no longer maintained (as indicated in comments below), yolk3kappears to be and supports Python 3.
yolk3k是2012 年yolk停止开发的原始版本的分支。虽然不再维护(如下面的评论所示),但似乎支持 Python 3。yolkyolk3k
Note:I am not involved in the development of yolk3k. If something doesn't seem to work as it should, leaving a comment here should not make much difference.Use the yolk3k issue trackerinstead and consider submitting a fix, if possible.
注意:我没有参与 yolk3k 的开发。如果某些事情似乎没有按预期工作,那么在这里发表评论应该没有太大区别。使用yolk3k问题跟踪,而不是和考虑提出一个解决方法,如果可能的话。
回答by Reiner Gerecke
After looking at pip's code for a while, it looks like the code responsible for locating packages can be found in the PackageFinderclass in pip.index. Its method find_requirementlooks up the versions of a InstallRequirement, but unfortunately only returns the most recent version.
看了一会pip的代码,貌似PackageFinder在pip.index. 它的方法find_requirement查找 a 的版本InstallRequirement,但不幸的是只返回最新版本。
The code below is almost a 1:1 copy of the original function, with the return in line 114 changed to return all versions.
下面的代码几乎是原始函数的 1:1 副本,将第 114 行中的返回更改为返回所有版本。
The script expects one package name as first and only argument and returns all versions.
该脚本需要一个包名作为第一个也是唯一的参数并返回所有版本。
I can't guarantee for the correctness, as I'm not familiar with pip's code.But hopefully this helps.
我不能保证正确性,因为我不熟悉 pip 的代码。但希望这会有所帮助。
Sample output
样本输出
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
The code:
编码:
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]
回答by m0she
https://pypi.python.org/pypi/Django/- works for packages whose maintainers choose to show all packages https://pypi.python.org/simple/pip/- should do the trick anyhow (lists all links)
https://pypi.python.org/pypi/Django/- 适用于维护者选择显示所有包的包 https://pypi.python.org/simple/pip/- 无论如何都应该做到这一点(列出所有链接)
回答by HVNSweeting
Update:
As of Sep 2017 this method no longer works: --no-installwas removed in pip 7
更新:
截至 2017 年 9 月,此方法不再有效:--no-install已在 pip 7 中删除
Use pip install -v, you can see all versions that available
使用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
To not install any package, use one of following solution:
要不安装任何软件包,请使用以下解决方案之一:
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
Tested with pip 1.0
使用 pip 1.0 测试
root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
回答by ykyuen
You could the yolk3k package instead of yolk. yolk3k is a fork from the original yolk and it supports both python2 and 3.
您可以使用 yolk3k 包而不是 yolk。yolk3k 是原始 yolk 的一个分支,它同时支持 python2 和 3。
pip install yolk3k
回答by Chris Montanaro
For pip >= 9.0use
对于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==
– all the available versions will be printed without actually downloading or installing any additional packages.
– 无需实际下载或安装任何其他软件包即可打印所有可用版本。
For pip < 9.0use
对于pip < 9.0使用
pip install pylibmc==blork
where blorkcan be any string that is not a valid version number.
whereblork可以是任何不是有效版本号的字符串。
回答by eric chiang
You don't need a third party package to get this information. pypi provides simple JSON feeds for all packages under
您不需要第三方包来获取此信息。pypi 为下面的所有包提供简单的 JSON 提要
https://pypi.python.org/pypi/{PKG_NAME}/json
Here's some Python code using only the standard library which gets all versions.
这是一些仅使用获取所有版本的标准库的 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"))
That code prints (as of Feb 23rd, 2015):
该代码打印(截至 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
回答by Andrew Magee
I didn't have any luck with yolk, yolk3kor pip install -vbut so I ended up using this (adapted to Python 3 from eric chiang's answer):
我没有任何运气yolk,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
...
回答by Timofey Stolbov
回答by Eugene Yarmash
You can use this small Python 3 script (using only standard library modules) to grab the list of available versions for a package from PyPI using JSON APIand print them in reverse chronological order. Unlike some other Python solutions posted here, this doesn't break on loose versions like django's 2.2rc1or uwsgi's 2.0.17.1:
您可以使用这个小的 Python 3 脚本(仅使用标准库模块)从使用JSON API 的PyPI 获取包的可用版本列表,并按时间倒序打印它们。与此处发布的其他一些 Python 解决方案不同,这不会在诸如django's2.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')
Save the script and run it with the package name as an argument, e.g.:
保存脚本并使用包名作为参数运行它,例如:
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
...

