Python和pip,列出可用的软件包的所有版本?


445

给定可以与pip一起安装的Python软件包的名称,是否有任何方法可以找到pip可以安装的所有可能版本的列表?现在是反复试验。

我正在尝试为第三方库安装一个版本,但是最新版本太新了,进行了向后不兼容的更改。所以我想以某种方式列出pip知道的所有版本,以便我可以对其进行测试。


1
可接受的答案与脚本的另一个答案不相同,因为它们不会生成相同的输出。
oligofren

17
请更新所选答案。蛋黄被打破,不需要。答案pip install pylibmc==是完美的。
乔纳森

请按照@Jonathan的建议更新接受的答案。我不会称其为完美,因为它不适用于较早版本的pip(v7或v8),但否则效果很好。
安东尼·哈奇金斯

1
@Rory请更新接受的答案,蛋黄死了。克里斯·蒙塔纳罗(Chris Montanaro)的答案是目前IMO的最佳方法。
瑞安·费舍尔

1
@Rory请更改接受的答案,以使将来的访问者受益于此热门问题。蛋黄项目不再维护,并且根本无法解决该问题。
wim

Answers:


167

(更新:截至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

yolk3k2012年yolk停止开发的原版的叉子。尽管已不再维护(如下面的注释所示),yolkyolk3k似乎并支持Python 3。

注意:我不参与yolk3k的开发。如果某些事情似乎无法正常工作,则在此处发表评论不会有太大的不同。请改用yolk3k问题追踪器,并考虑提交修订(如果可能)。


4
下面的答案(使用pastebin中的脚本)比较麻烦,但至少在我的情况下有效(搜索scipy的版本)。卵黄质仅显示最后一个可用版本,其他脚本显示所有可追溯到0.8.0的版本。
oligofren

30
大多数情况下,它只会返回最新版本
PawelRoman 2014年

17
杉木python3只需使用pip install yolk3k。yolk命令将可用。
Pierre Criulanscy 2015年

8
像蛋黄一样,大多数时候yolk3k只返回最新版本。
diabloneo 2015年

4
蛋黄被打破/不再维持。删除此答案。
wim

833

用于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

在哪里blork可以是不是有效版本号的任何字符串。


25
我发现pip的错误显示了所有版本,这很奇怪,但是它们没有任何参数可以明确获取所述数据
Chris Montanaro

2
该解决方案的另一个不错的特性是,它可以与所有常规标志一起使用来限制安装源。例如,pip install --only-binary :all: pylibmc将列出所有可用的pylibmc版本的二进制软件包。
pavon

3
pip install pylibmc==9999999 | tr ', ' "\n" | sort -n
维卡斯

18
应该将其标记为正确答案,因为它不需要安装任何其他软件包。
伊夫·多夫曼

5
这似乎是在pip中执行此操作的唯一方法,这有点荒谬。我希望他们的错误跟踪器至少对此有一个开放的问题?
pmos

69

更新:
自2017年9月起,此方法不再起作用:--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)

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 2015年

2
显示所有版本,只需要-v。我剩下的答案是为了避免增加效果(安装/下载)。对于已安装的pkg,只需添加--upgrade。可以,您可以创建一个单独的virtualenv来简化一切。
HVNSweeting

2
点9.0.1吠声:no such option: --no-install
疲倦的_nitpickers

-v中的“最新版本:”不包括某些版本。
mmacvicar

55

您不需要第三方软件包即可获取此信息。pypi为以下所有包提供了简单的JSON feed

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"))

该代码打印出来(截至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

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可以
容纳

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
Alan Ivey

1
ValueError对于某些遵循不太严格的版本控制方案的软件包,这将引发异常。要针对这些软件包进行修复,请参见本要点
TrinitronX

过时的将为您做到这一点。
shadi

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什么也没产生。我收到的警告wgetERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
三胞胎

sort -V不会对OSX用自制的版本中运行jq
deepelement


16

看了一段时间的pip代码后,看起来可以在中的PackageFinder类中找到负责定位软件包的代码pip.index。它的方法find_requirement查找的版本InstallRequirement,但不幸的是仅返回最新版本。

下面的代码几乎是原始函数的1:1副本,第114行的return更改为返回所有版本。

该脚本将一个包名称作为第一个也是唯一的参数,并返回所有版本。

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]

这比上面的答案要好得多。瘦$卵黄-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.90.0 0.9.0 0.9.0 0.8.0
oligofren

1
文档中明确建议不要使用这种用法:“ 您不得以这种方式使用pip的内部API
wim

9

您可以使用这个小的Python 3脚本(仅使用标准库模块)来使用JSON API从PyPI抓取软件包的可用版本列表,并以相反的时间顺序打印它们。不像其他一些Python的解决方案张贴在这里,但这并不松散的版本一样突破django2.2rc1还是uwsgi2.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


哎呀,你为什么还要发布这个答案。@Chris Montaro的答案有效且优雅。这只是不必要地引入了并发症
Brian Leach

@BrianLeach smh ...其过滤出的脚本使用的方法相同...
奶奶

1
我可以在cygwin / bash中工作,第二种解决方案使用sort,而不是cygwin中的gsort。
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')

通过查询https://pypi.org/的json API,它列出了可用软件包的所有版本。


如果您告诉我们您的软件包在做什么,那将更有启发性,否则,您只是在推广您的软件:)
user228395

@ user228395我认为这很明显,但是它列出了可用的软件包的所有版本,而这正是问题标题所要求的。编辑-更好吗?
wim

当然可以。因此,它实际上是包装@Timofey Stolbov提出的解决方案吗?
user228395 '19

1
@ user228395我不会称其为“包装”,因为该答案使用bash,curl和jq-而luddite仅使用Python标准库(urllib)。但是从Stolbov的解决方案确实使用在同一端点pypi.org。请问您投票否决的原因是什么?
wim

1
如果您单击链接到项目详细信息页面,则可以看到该项目的主要功能是关于检查requirements.txt文件中是否有过期的软件包。它不只是几行代码。为了检查requirements.txt文件,您需要具有列出所有软件包版本的功能。这部分是有意分离的,并且是luddite的公共API的一部分。它来自Apache License 2.0,我认为称其为“黑匣子”软件包确实不公平。
wim

2

我没有任何运气yolkyolk3kpip 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不会为许多软件包工作(djangouwsgipsycopg2仅举几例)。您可以使用parse_version()from setuptools(例如,请参见我的答案)。
尤金·雅玛什

1

另一种解决方案是使用Warehouse 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'])

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环境中更易于使用。

这个想法是提供一个全新的命令(在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

文档中明确建议不要使用这种用法:“ 您不得以这种方式使用pip的内部API
wim
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.