Python和PIP,列出可用的软件包的所有版本?
考虑到可以使用pip和virtualenv安装的Python(2.X)包的名称,是否有任何方法可以找出pip可以安装的所有可能版本的列表? 现在是试错。
我试图为第三方库安装一个版本,但是最新的版本太新了,所以出现了不兼容的变更。 所以我想以某种方式列出所有pip知道的版本,以便我可以testing它们。
在pastebin的脚本工作。 但是,如果您正在使用多个环境/主机,则不太方便,因为您必须每次都复制/创build它。
一个更好的全面的解决scheme将是使用蛋黄 ,这是可用与点安装。 比如看看Django有哪些版本可用:
$ 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,那么这可能是一个问题。
注:我没有参与蛋黄的发展。 如果某件事情看起来不像是应该的,那么在这里留言不应该有太大的改变。 如果可能,请使用蛋黄问题跟踪器,并考虑提交修补程序。
对于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==
– 所有可用的版本将被打印,而不会实际下载或安装任何额外的软件包。
对于点<9.0使用
pip install pylibmc==blork
blork
可以是任何不太可能成为安装候选者的string。
更新:
截至2017年9月,此方法不再有效: --no-install
no --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
要不安装任何软件包,请使用以下解决scheme之一:
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
testing与点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"))
该代码打印(截至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
在查看pip的代码一段时间后,它看起来像负责定位包的代码可以在pip.index
的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]
我想出了一个简单的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
更新:按版本号添加sorting。
https://pypi.python.org/pypi/Django/ – 适用于维护者select显示所有软件包的软件包https://pypi.python.org/simple/pip/ – 无论如何都应该这样做(列出所有链接)
PIP 7.1.0已经从安装中删除了–no-install选项。 我find了一个方法来获得一个包的所有版本,没有任何额外的包。
$ pip install --no-deps Django==xxx Collecting Django==xxx Could not find a version that satisfies the requirement Django==xxx (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==xxx
我对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 ...
我只是跑这个:
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:
我知道这是一种愚蠢的,但你可以尝试这样的事情:
pip install django == x
这将会出错,但会列出可用于此软件包的所有版本。
只要用你想要的软件包replacedjango
,我相信,希望没有这个版本叫做x。
您可以使用这个简短的Python3片段从PyPI获取一个包的可用版本列表。 与这里发布的其他Python解决scheme不同的是,它不会在django
的1.10rc1
或2.0.13.1
的1.10rc1
这样的松散版本中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 ...
这在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上)才能parsing版本。 你可以用brew install coreutils
来安装它
你可以grep您的pip list
的结果
-> % pip list | grep 'beautifulsoup4' beautifulsoup4 (4.4.1)