Python และ pip ​​แสดงรายการแพ็คเกจทั้งหมดที่ใช้ได้หรือไม่


445

ด้วยชื่อของแพ็คเกจ Python ที่สามารถติดตั้งด้วยpipได้มีวิธีใดบ้างที่จะตรวจสอบรายการของรุ่นที่เป็นไปได้ทั้งหมดที่ pip สามารถติดตั้งได้ ตอนนี้เป็นการทดลองและข้อผิดพลาด

ฉันกำลังพยายามติดตั้งเวอร์ชันสำหรับห้องสมุดบุคคลที่สาม แต่รุ่นใหม่ล่าสุดนั้นใหม่เกินไปก็มีการเปลี่ยนแปลงที่เข้ากันไม่ได้ย้อนหลัง ดังนั้นฉันอยากจะมีรายชื่อของทุกรุ่นที่ pip รู้เกี่ยวกับเพื่อให้ฉันสามารถทดสอบพวกเขา


1
คำตอบที่ยอมรับนั้นไม่เท่ากับคำตอบอื่นที่มีสคริปต์เนื่องจากคำตอบนั้นไม่ได้สร้างผลลัพธ์เดียวกัน
oligofren

17
โปรดอัปเดตคำตอบที่เลือก ไข่แดงแตกและไม่ต้องการ คำตอบpip install pylibmc==ที่สมบูรณ์แบบ
Jonathan

โปรดอัปเดตคำตอบที่ยอมรับเนื่องจาก @Jonathan แนะนำ ฉันจะไม่เรียกมันว่าสมบูรณ์แบบเพราะมันจะใช้งานไม่ได้กับ pip รุ่นก่อนหน้า (v7 หรือ v8) แต่มันยอดเยี่ยมมาก
Antony Hatchkins

1
@ โรรี่โปรดอัปเดตคำตอบที่ยอมรับไข่แดงนั้นตาย คำตอบของ Chris Montanaro เป็นวิธีที่ดีที่สุดในปัจจุบัน IMO
Ryan Fisher

1
@Rory โปรดเปลี่ยนคำตอบที่ยอมรับเพื่อประโยชน์ของผู้เยี่ยมชมในอนาคตสำหรับคำถามยอดนิยมนี้ โครงการไข่แดงไม่ได้รับการดูแลรักษาอีกต่อไปและมันก็ไม่ได้ผลเหมือนคำตอบที่อ้าง
Wim

คำตอบ:


167

(อัปเดต: ณ เดือนมีนาคม 2563 หลายคนรายงานว่าไข่แดงติดตั้งผ่านpip install yolk3kจะส่งคืนเวอร์ชันล่าสุดเท่านั้น คำตอบของคริสดูเหมือนจะมี upvotes มากที่สุดและทำงานให้ฉัน)

สคริปต์ที่ 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เป็นทางแยกของเดิมyolkที่หยุดการพัฒนาใน2012 แม้ว่าyolkจะไม่ได้รับการบำรุงรักษาอีกต่อไป (ตามที่ระบุไว้ในความคิดเห็นด้านล่าง) yolk3kดูเหมือนจะเป็นและสนับสนุน Python 3

หมายเหตุ:ฉันไม่ได้มีส่วนร่วมในการพัฒนา yolk3k หากสิ่งที่ดูเหมือนจะไม่ทำงานตามที่ควรการแสดงความคิดเห็นที่นี่ไม่ควรสร้างความแตกต่างมาก ใช้ตัวติดตามปัญหา yolk3kแทนและพิจารณาส่งการแก้ไขถ้าเป็นไปได้


4
คำตอบด้านล่าง (การใช้สคริปต์จาก pastebin) นั้นยุ่งยากกว่า แต่อย่างน้อยก็ใช้ได้ในกรณีของฉัน (ค้นหาเวอร์ชั่นของ scipy) ไข่แดงแสดงเฉพาะรุ่นล่าสุดที่มีอยู่สคริปต์อื่นแสดงทุกรุ่นย้อนหลังไปถึง 0.8.0
oligofren

30
ส่วนใหญ่แล้วจะส่งคืนเวอร์ชันใหม่ล่าสุดเท่านั้น
PawelRoman

17
เฟอร์ python3 เพียงใช้ pip ติดตั้ง yolk3k คำสั่ง yolk จะพร้อมใช้งาน
Pierre Criulanscy

8
เช่นเดียวกับไข่แดงส่วนใหญ่เวลา yolk3k เพียงกลับรุ่นใหม่ล่าสุด
diabloneo

4
ไข่แดงแตก / ไม่มีการดูแลอีกต่อไป ลบคำตอบนี้
Wim

836

สำหรับ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
Vikas

18
ควรทำเครื่องหมายเป็นคำตอบที่ถูกต้องเนื่องจากไม่จำเป็นต้องติดตั้งแพ็กเกจอื่น
Yves Dorfsman

5
มันไร้สาระนิดหน่อยที่นี่ดูเหมือนจะเป็นวิธีเดียวที่จะทำได้ใน pip ฉันหวังว่าอย่างน้อยจะมีปัญหาแบบเปิดเกี่ยวกับเรื่องนี้ในเครื่องมือติดตามบั๊ก
pmos

69

อัปเดต:
ณ วันที่ 2017 กันยายนวิธีนี้ใช้งานไม่ได้อีกต่อไป: --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

หรือ

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

2
-vที่จะแสดงให้ทุกรุ่นเป็นเพียงความต้องการ ส่วนที่เหลือของคำตอบของฉันคือการหลีกเลี่ยงผลกระทบเพิ่มเติม (ติดตั้ง / ดาวน์โหลด) สำหรับ pkg ที่ติดตั้งเพียงเพิ่ม - อัปเกรด และคุณสามารถสร้าง virtualenv แยกต่างหากเพื่อทำให้ทุกอย่างง่ายขึ้น
HVNSweeting

2
pip 9.0.1 barks:no such option: --no-install
เหนื่อย_of_nitpickers

"รุ่นใหม่ล่าสุด:" จาก -v ไม่รวมบางรุ่น
mmacvicar

55

คุณไม่จำเป็นต้องมีแพ็คเกจของบุคคลที่สามเพื่อรับข้อมูลนี้ pypi จัดให้มีฟีด JSON อย่างง่ายสำหรับทุกแพ็คเกจภายใต้

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

นี่คือบางโค้ดไพ ธ อนที่ใช้เฉพาะไลบรารี่มาตรฐานที่รับทุกเวอร์ชั่น

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

รหัสนั้นจะพิมพ์ออกมา (ณ วันที่ 23 กุมภาพันธ์ 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 มีการซ้อนจำนวนที่เหมาะสม ฉันเคย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ดังนั้นฉันจึงคาดการณ์ว่าอาจมีอยู่ในแพ็คเกจอื่น)
tripleee

2
นี่เป็นวิธีที่จะทำกับขด jq และเรียงลำดับ ("หนึ่งซับ"!): 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
อลันไอวี่ย์

1
สิ่งนี้ทำให้เกิดValueErrorข้อยกเว้นสำหรับบางแพ็กเกจที่ตามมาไม่เข้มงวดมาก เมื่อต้องการแก้ไขสำหรับแพ็คเกจเหล่านี้ให้ดูส่วนสำคัญนี้
TrinitronX

ล้าสมัยจะทำเช่นนี้เพื่อคุณ
shadi

18

ฉันมากับสคริปต์ทุบตีที่เรียบง่าย ขอบคุณผู้เขียน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ไม่มีผลอะไรเลย คำเตือนที่ฉันwgetพูดด้วยERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
tripleee

The sort -Vไม่ทำงานบน OSX กับเวอร์ชันของ homebrewjq
deepelement

16

คุณสามารถใช้แพ็คเกจ yolk3k แทนไข่แดงได้ yolk3k เป็นทางแยกจากไข่แดงดั้งเดิมและรองรับทั้ง python2 และ 3

https://github.com/myint/yolk

pip install yolk3k

สิ่งนี้มีประโยชน์ที่จะรู้ตั้งแต่ไข่แดงไม่ทำงานภายใต้ python 3.x
Broken Man

1
ผลตอบแทน yolk3k เพียงรุ่นที่ติดตั้งสำหรับฉัน:yolk -V attest Attest 0.5.3
แอนโทนี Hatchkins

2
yolk3k ดูเหมือนจะส่งคืนเวอร์ชันล่าสุดเท่านั้นหรือ
mvherweg

16

หลังจากดูที่รหัสของ pip ในขณะที่ดูเหมือนว่ารหัสที่รับผิดชอบในตำแหน่งแพคเกจที่สามารถพบได้ในชั้นเรียนPackageFinder pip.indexวิธีการของมันfind_requirementจะค้นหาเวอร์ชั่นของ a 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]

วิธีนี้ใช้ได้ดีกว่าคำตอบข้างต้นทั้งหมด ผอม $ yolk -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.9.0 0.9.0 0.8.0
oligofren

1
การใช้งานนี้ไม่ได้รับการสนับสนุนอย่างชัดเจนในเอกสาร : " คุณต้องไม่ใช้ API ภายในของ pip ด้วยวิธีนี้ "
wim

9

คุณสามารถใช้สคริปต์ Python 3 ขนาดเล็กนี้ (ใช้เฉพาะโมดูลไลบรารีมาตรฐาน) เพื่อคว้ารายการเวอร์ชันที่มีอยู่สำหรับแพ็คเกจจาก PyPI โดยใช้JSON APIและพิมพ์ตามลำดับเวลาย้อนกลับ ไม่เหมือนกับโซลูชัน Python อื่น ๆ ที่โพสต์ไว้ที่นี่ แต่จะไม่แตกรุ่นที่หลวมเช่นdjango's 2.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')

บันทึกสคริปต์และเรียกใช้ด้วยชื่อแพ็คเกจเป็นอาร์กิวเมนต์เช่น:

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


Jeez ทำไมคุณถึงโพสต์คำตอบนี้ด้วยซ้ำ คำตอบของ @Chris Montaro ทำงานได้และสง่างาม นี่เป็นเพียงการแนะนำภาวะแทรกซ้อนโดยไม่จำเป็น
Brian Leach

@BrianLeach SMH ... วิธีการของมันเหมือนกันกรองสำหรับใช้ในสคริปต์ ...
ยาย

1
ทำงานใน cygwin / bash สำหรับฉันสำหรับวิธีที่สองใช้การเรียงลำดับไม่ใช่ gsort ใน cygwin
ดูแลเว็บ

หลามที่นี่ให้โค้ดที่อ่านได้ง่ายกว่าทุบตี ... ดูคำตอบของ @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')

มันแสดงรายการแพคเกจทุกรุ่นที่มีอยู่โดยการสืบค้น json API ของhttps://pypi.org/


มันจะเป็นคำแนะนำเพิ่มเติมถ้าคุณจะบอกเราว่าแพคเกจของคุณกำลังทำอะไรอยู่มิฉะนั้นคุณเพียงแค่โปรโมตซอฟต์แวร์ของคุณ :)
228395

@ user228395 ฉันคิดว่ามันชัดเจนเพียงพอ แต่แสดงรายการแพคเกจทุกรุ่นที่มีให้ซึ่งเป็นสิ่งที่ชื่อของคำถามถาม แก้ไข - ดีกว่าไหม
Wim

ผลงานแน่นอน ดังนั้นจึงจำเป็นต้องห่อหุ้มโซลูชันที่นำเสนอโดย @Timofey Stolbov?
user228395

1
@ user228395 ฉันจะไม่เรียกมันว่า "การตัด" เนื่องจากคำตอบนั้นใช้ bash, curl และ jq - ในขณะที่ luddite ก็ใช้ไลบรารี่มาตรฐานของ Python (urllib) แต่การแก้ปัญหาจาก Stolbov ไม่ใช้ปลายทางเดียวกันในpypi.org ฉันขอถามเหตุผลของ downvote ของคุณได้ไหม
Wim

1
หากคุณติดตามลิงก์ไปยังหน้ารายละเอียดโครงการคุณจะเห็นว่าคุณสมบัติหลักของโครงการเกี่ยวกับการตรวจสอบrequirements.txtไฟล์สำหรับแพ็คเกจล้าสมัย มันเป็นมากกว่าสองบรรทัดของรหัส ในการตรวจสอบrequirements.txtไฟล์คุณต้องมีฟังก์ชั่นเพื่อแสดงรายการแพ็คเกจทั้งหมด ส่วนนี้ถูกแยกออกโดยเจตนาและเป็นส่วนหนึ่งของ API สาธารณะของ luddite และเป็นแหล่งที่มา Apache License 2.0 ฉันคิดว่ามันไม่ยุติธรรมเลยที่จะเรียกว่าแพคเกจซอฟต์แวร์ "กล่องดำ"
Wim

2

ฉันไม่ได้มีโชคใด ๆ กับyolk, yolk3kหรือpip install -vแต่ผมก็เลยจบลงด้วยการใช้นี้ (ปรับให้เข้ากับงูหลาม 3 จากคำตอบ eric เชียงใหม่):

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จะไม่ทำงานสำหรับแพคเกจจำนวนมาก ( django, uwsgi, psycopg2เพื่อชื่อไม่กี่) คุณสามารถใช้parse_version()จากsetuptools(ดูคำตอบของฉันสำหรับตัวอย่าง)
Eugene Yarmash

1

ทางเลือกอื่นคือใช้ API ของ Warehouse:

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

My take คือการรวมกันของสองคำตอบโพสต์ด้วยการปรับเปลี่ยนบางอย่างเพื่อให้ง่ายต่อการใช้จากภายในสภาพแวดล้อมที่ทำงานหลาม

แนวคิดคือจัดเตรียมคำสั่งใหม่ทั้งหมด (จำลองหลังจากคำสั่งติดตั้ง) ที่ให้อินสแตนซ์ของตัวค้นหาแพ็คเกจที่จะใช้ ข้อเสียคือมันทำงานร่วมกับและใช้ดัชนีใด ๆ ที่ 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 ภายในของ pip ด้วยวิธีนี้ "
wim
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.