Python và pip, liệt kê tất cả các phiên bản của một gói có sẵn?


445

Đặt tên của gói Python có thể được cài đặt bằng pip , có cách nào để tìm ra danh sách tất cả các phiên bản có thể có của gói mà pip có thể cài đặt không? Ngay bây giờ, nó là bản dùng thử và lỗi.

Tôi đang cố gắng cài đặt phiên bản cho thư viện bên thứ ba, nhưng phiên bản mới nhất quá mới, có những thay đổi không tương thích ngược được thực hiện. Vì vậy, bằng cách nào đó tôi muốn có một danh sách tất cả các phiên bản mà pip biết, để tôi có thể kiểm tra chúng.


1
Câu trả lời được chấp nhận không tương đương với câu trả lời khác với tập lệnh vì chúng không tạo ra cùng một đầu ra.
oligofren

17
Vui lòng cập nhật câu trả lời đã chọn. Lòng đỏ bị hỏng và không cần thiết. Câu trả lời với pip install pylibmc==là hoàn hảo.
Jonathan

Vui lòng cập nhật câu trả lời được chấp nhận như @Jonathan gợi ý. Tôi sẽ không gọi nó là hoàn hảo bởi vì nó sẽ không hoạt động trên các phiên bản trước của pip (v7 hoặc v8), nhưng thật tuyệt vời.
Antony Hatchkins

1
@Rory vui lòng cập nhật câu trả lời được chấp nhận, lòng đỏ đã chết. Câu trả lời của Chris Montanaro là phương pháp tốt nhất hiện nay IMO.
Ryan Fisher

1
@Rory Vui lòng thay đổi câu trả lời được chấp nhận vì lợi ích của khách truy cập trong tương lai cho câu hỏi phổ biến này. Dự án lòng đỏ không còn được duy trì và đơn giản là nó không hoạt động như câu trả lời đó.
wim

Câu trả lời:


167

(cập nhật: Kể từ tháng 3 năm 2020, nhiều người đã báo cáo rằng lòng đỏ, được cài đặt qua pip install yolk3k, chỉ trả về phiên bản mới nhất. Câu trả lời của Chris dường như có nhiều sự ủng hộ và hiệu quả nhất đối với tôi)

Kịch bản tại pastebin không hoạt động. Tuy nhiên, sẽ không thuận tiện lắm nếu bạn làm việc với nhiều môi trường / máy chủ vì bạn sẽ phải sao chép / tạo nó mỗi lần.

Một giải pháp toàn diện tốt hơn sẽ là sử dụng yolk3k , có sẵn để cài đặt với pip. Ví dụ để xem phiên bản nào của Django có sẵn:

$ 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

yolk3klà một ngã ba của bản gốc yolkđã ngừng phát triển vào năm 2012 . Mặc dù yolkkhông còn được duy trì (như được nêu trong các bình luận bên dưới), yolk3kdường như và hỗ trợ Python 3.

Lưu ý: Tôi không tham gia vào sự phát triển của yolk3k. Nếu một cái gì đó dường như không hoạt động như bình thường, để lại một bình luận ở đây sẽ không làm cho nhiều sự khác biệt. Thay vào đó, hãy sử dụng trình theo dõi sự cố yolk3k và xem xét gửi bản sửa lỗi, nếu có thể.


4
Câu trả lời dưới đây (sử dụng tập lệnh từ pastebin) thì cồng kềnh hơn, nhưng ít nhất là hoạt động trong trường hợp của tôi (tìm kiếm các phiên bản của scipy). lòng đỏ chỉ hiển thị phiên bản cuối cùng có sẵn, tập lệnh khác hiển thị tất cả các phiên bản có niên đại từ 0.8.0.
oligofren

30
Hầu hết thời gian nó sẽ chỉ trở lại phiên bản mới nhất
PawelRoman

17
Fir python3 chỉ cần sử dụng pip cài đặt yolk3k. Lệnh lòng đỏ sẽ có sẵn.
Pierre Criulanscy

8
Giống như lòng đỏ, hầu hết thời gian yolk3k chỉ trả về phiên bản mới nhất.
diabloneo

4
lòng đỏ bị hỏng / không còn duy trì. xóa câu trả lời này
wim

834

Đối với pip> = 9.0 sử dụng

$ 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==

- tất cả các phiên bản có sẵn sẽ được in mà không thực sự tải xuống hoặc cài đặt bất kỳ gói bổ sung nào.

Đối với pip <9.0 sử dụng

pip install pylibmc==blork

trong đó blorkcó thể là bất kỳ chuỗi nào không phải là số phiên bản hợp lệ .


25
Tôi thấy thật kỳ lạ khi lỗi của pip phát sinh ra tất cả các phiên bản nhưng chúng không có đối số để có được dữ liệu rõ ràng
Chris Montanaro

2
Một đặc tính tốt khác của giải pháp này là nó hoạt động với tất cả các cờ bình thường để hạn chế nguồn cài đặt. Ví dụ pip install --only-binary :all: pylibmcsẽ liệt kê tất cả các phiên bản của pylibmc có sẵn dưới dạng các gói nhị phân.
pavon

3
pip install pylibmc==9999999 | tr ', ' "\n" | sort -n
Vikas

18
Điều này nên được đánh dấu là câu trả lời chính xác vì nó không bắt buộc phải cài đặt bất kỳ gói nào khác.
Yves Dorfsman

5
Có một chút nực cười khi đây dường như là cách duy nhất để làm điều này trong pip. Tôi hy vọng có ít nhất một vấn đề mở về vấn đề này trên trình theo dõi lỗi của họ?
pmos

69

Cập nhật:
Kể từ tháng 9 năm 2017 phương pháp này không còn hoạt động: --no-installđã bị xóa trong pip 7

Sử dụng pip install -v, bạn có thể thấy tất cả các phiên bản có sẵn

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

Để không cài đặt bất kỳ gói nào, hãy sử dụng một trong các giải pháp sau:

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

hoặc là

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

Đã thử nghiệm với pip 1.0

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)

9
pip 1.5.4cung cấp DEPRECATION: --no-install, --no-download, --build, and --no-clean are deprecated. See https://github.com/pypa/pip/issues/906.và không hiển thị các phiên bản có sẵn cho các gói đã được cài đặt.
int_ua

2
để hiển thị tất cả các phiên bản, nó chỉ cần -v. Phần còn lại của câu trả lời của tôi là để tránh hiệu ứng bổ sung (cài đặt / tải xuống). Để cài đặt pkg, chỉ cần thêm - nâng cấp. Anw, bạn có thể tạo một virtualenv riêng để làm mọi thứ đơn giản hơn.
HVNSweeting

2
tiếng sủa của pip 9.0.1:no such option: --no-install
mệt mỏi_of_nitopperers

"phiên bản mới nhất:" từ -v không bao gồm một số phiên bản.
mmacvicar

55

Bạn không cần gói bên thứ ba để có được thông tin này. pypi cung cấp nguồn cấp JSON đơn giản cho tất cả các gói trong

https://pypi.python.org/pypi/{PKG_NAME}/json

Đây là một số mã Python chỉ sử dụng thư viện chuẩn có tất cả các phiên bản.

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

Mã đó được in (kể từ ngày 23 tháng 2 năm 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

2
JSON có số lượng lồng nhau khá lớn. Tôi đã sử dụng versions = [x for x in data["releases"] if any([y["python_version"] in ['cp26', '2.6'] for y in data["releases"][x]])]để tìm các phiên bản tương thích với Python 2.6. (Tôi không thấy ở cp26bất cứ đâu, nhưng một số gói đã có cp27vì vậy tôi suy đoán rằng điều này có thể tồn tại trong các gói khác.)
tripleee 18/03/2016

2
Đây là một cách để làm điều đó với curl, jq và sort (một "lớp lót"!): 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
Điều này đưa ra một ValueErrorngoại lệ cho một số gói tuân theo các sơ đồ phiên bản không quá nghiêm ngặt. Để sửa nó cho các gói này, xem ý chính này .
TrinitronX

lỗi thời sẽ làm điều này cho bạn.
shadi

18

Tôi đã đưa ra kịch bản bash chết đơn giản. Cảm ơn tác giả của 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

Cập nhật: Thêm sắp xếp theo số phiên bản.


Tôi đã không thể đi curllàm, có thể là do lỗi chứng chỉ. wget --no-check-certificatehoạt động, nhưng thậm chí curl -k --insecurekhông sản xuất được gì. Cảnh báo tôi nhận được wgetnóiERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
tripleee 18/03/2016

Công cụ sort -Vnày không hoạt động trên OSX với phiên bản của homebrewjq
deepelement

16

Bạn có thể gói yolk3k thay vì lòng đỏ. yolk3k là một ngã ba từ lòng đỏ ban đầu và nó hỗ trợ cả python2 và 3.

https://github.com/myint/yol

pip install yolk3k

Điều này rất hữu ích để biết, vì lòng đỏ không hoạt động theo python 3.x
Broken Man

1
yolk3k chỉ trả lại phiên bản đã cài đặt cho tôi:yolk -V attest Attest 0.5.3
Antony Hatchkins

2
yolk3k dường như chỉ trả lại phiên bản mới nhất?
mvherweg

16

Sau khi xem mã của pip một lúc, có vẻ như mã chịu trách nhiệm định vị các gói có thể được tìm thấy trong PackageFinderlớp pip.index. Phương pháp của nó find_requirementtìm kiếm các phiên bản của a InstallRequirement, nhưng không may chỉ trả về phiên bản gần đây nhất.

Mã bên dưới gần như là bản sao 1: 1 của hàm gốc, với dòng trả về trong dòng 114 đã thay đổi để trả về tất cả các phiên bản.

Kịch bản lệnh mong muốn một tên gói là đối số đầu tiên và duy nhất và trả về tất cả các phiên bản.

http://pastebin.com/axzdUQhZ

Tôi không thể đảm bảo tính chính xác, vì tôi không quen với mã của pip. Nhưng hy vọng điều này sẽ giúp.

Sản lượng mẫu

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

Mật mã:

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]

Điều này làm việc tốt hơn rất nhiều so với câu trả lời ở trên. skinny $ lòng đỏ -V scipy scipy 0.12.0 skinny $ python test.py scipy Phiên bản của 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.9.0 0.9.0 0.8.0
oligofren

1
Việc sử dụng này được khuyến khích rõ ràng trong các tài liệu : " bạn không được sử dụng API nội bộ của pip theo cách này "
wim

9

Bạn có thể sử dụng tập lệnh Python 3 nhỏ này (chỉ sử dụng các mô-đun thư viện tiêu chuẩn) để lấy danh sách các phiên bản có sẵn cho gói từ PyPI bằng API JSON và in chúng theo thứ tự thời gian đảo ngược. Không giống như một số giải pháp Python khác được đăng ở đây, điều này không phá vỡ các phiên bản lỏng lẻo như django's 2.2rc1hoặc 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')

Lưu tập lệnh và chạy nó với tên gói làm đối số, ví dụ:

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

Điều này hoạt động với tôi trên OSX:

pip install docker-compose== 2>&1 \
| grep -oE '(\(.*\))' \
| awk -F:\  '{print$NF}' \
| sed -E 's/( |\))//g' \
| tr ',' '\n'

Nó trả về danh sách một trên mỗi dòng:

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

Hoặc để có phiên bản mới nhất có sẵn:

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

Hãy nhớ rằng gsortphải được cài đặt (trên OSX) để phân tích các phiên bản. Bạn có thể cài đặt nó vớibrew install coreutils


Jeez tại sao bạn thậm chí đăng câu trả lời này. Câu trả lời của @Chris Montaro hoạt động và thanh lịch. Điều này chỉ cần giới thiệu sự phức tạp
Brian Leach

@BrianLeach smh ... cách tiếp cận tương tự được lọc để sử dụng trong một kịch bản ...

1
Hoạt động trong cygwin / bash đối với tôi, đối với giải pháp thứ hai sử dụng sort, không phải gsort trong cygwin.
WebComer

Ở đây, sản lượng trăn được cho là mã dễ đọc hơn bash ... xem phần trả lời của @eric chiang (hy vọng :) ở trên ...
mirekphd

4

Dự án của tôi ludditecó tính năng này.

Ví dụ sử dụng:

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

Nó liệt kê tất cả các phiên bản của một gói có sẵn, bằng cách truy vấn API json của https://pypi.org/


Sẽ tốt hơn nếu bạn cho chúng tôi biết gói của bạn đang làm gì, nếu không bạn chỉ đang quảng bá phần mềm của mình :)
user228395 16/11/19

@ user228395 Tôi nghĩ rằng nó đã đủ rõ ràng, nhưng nó liệt kê tất cả các phiên bản của một gói có sẵn, đó chính xác là tiêu đề của câu hỏi. Chỉnh sửa - tốt hơn?
wim

Hoạt động của nó tất nhiên. Vì vậy, về cơ bản nó là gói giải pháp được trình bày bởi @Timofey Stolbov?
dùng228395

1
@ user228395 Tôi sẽ không gọi nó là "gói", vì câu trả lời đó sử dụng bash, curl và jq - trong khi luddite chỉ sử dụng thư viện chuẩn Python (urllib). Nhưng giải pháp từ Stolbov không sử dụng cùng một điểm cuối trên pypi.org . Tôi có thể hỏi lý do cho downvote của bạn là gì?
wim

1
Nếu bạn đã theo liên kết đến trang chi tiết dự án, bạn có thể thấy rằng tính năng chính của dự án là về việc kiểm tra requirements.txtcác tệp cho các gói hết hạn. Nó là nhiều hơn một vài dòng mã. Để kiểm tra một requirements.txttập tin, bạn cần có chức năng liệt kê tất cả các phiên bản gói. Phần này được cố ý tách rời và một phần của API công khai của luddite. Và đó là nguồn Apache License 2.0, tôi nghĩ thật không công bằng khi gọi đó là gói phần mềm "hộp đen".
wim

2

Tôi không có bất kỳ may mắn với yolk, yolk3khoặc pip install -vnhưng vì vậy tôi đã kết thúc sử dụng này (thích nghi với Python 3 từ câu trả lời eric chiang của):

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
StrictVersionsẽ không làm việc cho nhiều gói ( django, uwsgi, psycopg2đến tên một vài). Bạn có thể sử dụng parse_version()từ setuptools(xem câu trả lời của tôi cho một ví dụ).
Eugene Yarmash

1

Giải pháp thay thế là sử dụng API kho:

https://warehouse.readthedocs.io/api-reference/json/#release

Ví dụ cho Flask:

import requests
r = requests.get("https://pypi.org/pypi/Flask/json")
print(r.json()['releases'].keys())

sẽ in:

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

bashKịch bản đơn giản chỉ dựa vào pythonchính nó (tôi giả sử rằng trong bối cảnh của câu hỏi nên được cài đặt) và một trong curlhoặc wget. Nó có một giả định rằng bạn đã setuptoolscài đặt gói để sắp xếp các phiên bản (hầu như luôn được cài đặt). Nó không phụ thuộc vào các phụ thuộc bên ngoài như:

  • jq mà có thể không có mặt;
  • grepawkđiều đó có thể hành xử khác nhau trên Linux và 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)))"

Một phiên bản dài hơn một chút với ý kiến.

Đặt tên gói vào một biến:

PACKAGE=requests

Nhận phiên bản (sử dụng 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)))")

Nhận phiên bản (sử dụng 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)))")

In các phiên bản đã sắp xếp:

echo $VERSIONS

-1

My Take là sự kết hợp của một vài câu trả lời được đăng, với một số sửa đổi để làm cho chúng dễ sử dụng hơn trong môi trường python đang chạy.

Ý tưởng là cung cấp một lệnh hoàn toàn mới (được mô phỏng theo lệnh cài đặt) cung cấp cho bạn một phiên bản của trình tìm gói để sử dụng. Ưu điểm là nó hoạt động với và sử dụng bất kỳ chỉ mục nào mà pip hỗ trợ và đọc các tệp cấu hình pip cục bộ của bạn, để bạn có được kết quả chính xác như khi cài đặt pip bình thường.

Tôi đã cố gắng làm cho nó tương thích với cả pip v 9.x và 10.x .. nhưng chỉ thử nó trên 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())

Ví dụ đầu ra

./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

việc sử dụng này rõ ràng không được khuyến khích trong các tài liệu : " bạn không được sử dụng API nội bộ của pip theo cách này "
wim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.