Python und Pip, alle verfügbaren Versionen eines Pakets auflisten?

445

Gibt es angesichts des Namens eines Python-Pakets, das mit pip installiert werden kann , eine Möglichkeit, eine Liste aller möglichen Versionen davon herauszufinden, die pip installieren könnte? Im Moment ist es Versuch und Irrtum.

Ich versuche, eine Version für eine Bibliothek eines Drittanbieters zu installieren, aber die neueste Version ist zu neu. Es wurden rückwärts inkompatible Änderungen vorgenommen. Ich hätte gerne eine Liste aller Versionen, die pip kennt, damit ich sie testen kann.

Rory
quelle
1
Die akzeptierte Antwort entspricht nicht der anderen mit dem Skript, da sie nicht dieselbe Ausgabe generieren.
Oligofren
17
Bitte aktualisieren Sie die ausgewählte Antwort. Eigelb ist gebrochen und nicht nötig. Die Antwort mit pip install pylibmc==ist perfekt.
Jonathan
Bitte aktualisieren Sie die akzeptierte Antwort wie von Jonathan vorgeschlagen. Ich würde es nicht als perfekt bezeichnen, da es auf früheren Versionen von pip (v7 oder v8) nicht funktioniert, aber ansonsten ist es großartig.
Antony Hatchkins
1
@Rory bitte aktualisiere die akzeptierte Antwort, Eigelb ist tot. Chris Montanaros Antwort ist die derzeit beste Methode IMO.
Ryan Fisher
1
@Rory Bitte ändern Sie die akzeptierte Antwort zum Nutzen zukünftiger Besucher dieser beliebten Frage. Das Yolk-Projekt wird nicht mehr gewartet und funktioniert einfach nicht, wie diese Antwort behauptet.
wim

Antworten:

167

(Update: Ab März 2020 haben viele Leute berichtet, dass Eigelb, installiert über pip install yolk3k, nur die neueste Version zurückgibt. Chris 'Antwort scheint die meisten positiven Stimmen zu haben und hat für mich funktioniert.)

Das Skript bei Pastebin funktioniert. Es ist jedoch nicht sehr praktisch, wenn Sie mit mehreren Umgebungen / Hosts arbeiten, da Sie es jedes Mal kopieren / erstellen müssen.

Eine bessere Allround-Lösung wäre die Verwendung von yolk3k , das für die Installation mit pip verfügbar ist. ZB um zu sehen, welche Versionen von Django verfügbar sind:

$ 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

yolk3kist eine Gabelung des Originals, yolkderen Entwicklung 2012 eingestellt wurde . Obwohl yolkes nicht mehr gepflegt wird (wie in den Kommentaren unten angegeben), yolk3kscheint es Python 3 zu sein und unterstützt es.

Hinweis: Ich bin nicht an der Entwicklung von yolk3k beteiligt. Wenn etwas nicht so zu funktionieren scheint, wie es sollte, sollte es keinen großen Unterschied machen, hier einen Kommentar zu hinterlassen. Verwenden Sie stattdessen den yolk3k Issue Tracker und erwägen Sie, wenn möglich, einen Fix einzureichen.

m000
quelle
4
Die Antwort unten (unter Verwendung des Skripts von Pastebin) ist umständlicher, funktioniert aber zumindest in meinem Fall (Suche nach Versionen von scipy). yolk zeigt nur die letzte verfügbare Version an, das andere Skript zeigt alle Versionen, die auf 0.8.0 zurückgehen.
Oligofren
30
Meistens wird nur die neueste Version zurückgegeben
PawelRoman
17
Fir python3 benutze einfach pip install yolk3k. Der Befehl yolk ist verfügbar.
Pierre Criulanscy
8
Wie bei yolk gibt yolk3k meistens nur die neueste Version zurück.
Diabloneo
4
Eigelb ist gebrochen / wird nicht mehr gepflegt. Löschen Sie diese Antwort.
wim
834

Für pip> = 9.0 verwenden

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

- Alle verfügbaren Versionen werden gedruckt, ohne dass zusätzliche Pakete heruntergeladen oder installiert werden müssen.

Für pip <9.0 verwenden

pip install pylibmc==blork

Dabei blorkkann es sich um eine beliebige Zeichenfolge handeln, die keine gültige Versionsnummer ist .

Chris Montanaro
quelle
25
Ich finde es seltsam, dass Pips Fehler alle Versionen ausspuckt, aber sie haben kein Argument, um explizit auf diese Daten
Chris Montanaro
2
Eine weitere nette Eigenschaft dieser Lösung ist, dass sie mit allen normalen Flags funktioniert, um die Installationsquellen zu begrenzen. Beispielsweise pip install --only-binary :all: pylibmcwerden alle Versionen von pylibmc aufgelistet, die als Binärpakete verfügbar sind.
Pavon
3
pip install pylibmc==9999999 | tr ', ' "\n" | sort -n
Vikas
18
Dies sollte als die richtige Antwort markiert werden, da keine anderen Pakete installiert werden müssen.
Yves Dorfsman
5
Es ist ein bisschen lächerlich, dass dies der einzige Weg zu sein scheint, dies in pip zu tun. Ich hoffe, es gibt zumindest ein offenes Problem dazu auf ihrem Bug-Tracker?
pmos
69

Update:
Ab September 2017 funktioniert diese Methode nicht mehr: --no-installwurde in Pip 7 entfernt

Verwenden pip install -vSie, um alle verfügbaren Versionen anzuzeigen

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

Verwenden Sie eine der folgenden Lösungen, um kein Paket zu installieren:

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

oder

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

Getestet mit Pip 1.0

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
HVNSweeting
quelle
9
pip 1.5.4Gibt DEPRECATION: --no-install, --no-download, --build, and --no-clean are deprecated. See https://github.com/pypa/pip/issues/906.verfügbare Versionen für bereits installierte Pakete an und zeigt sie nicht an.
int_ua
2
Um alle Versionen anzuzeigen, muss es nur -v. Der Rest meiner Antwort dient der Vermeidung von Additionseffekten (Installation / Download). Für installiertes Paket fügen Sie einfach --upgrade hinzu. Anw, Sie können eine separate virtuelle Umgebung erstellen, um alles einfacher zu machen.
HVNSweeting
2
pip 9.0.1 bellt:no such option: --no-install
müde_von_nitpickers
"neueste Version:" von -v schließt einige Versionen aus.
mmacvicar
55

Sie benötigen kein Paket eines Drittanbieters, um diese Informationen zu erhalten. pypi bietet einfache JSON-Feeds für alle Pakete unter

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

Hier ist etwas Python-Code, der nur die Standardbibliothek verwendet, die alle Versionen erhält.

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

Dieser Code wird gedruckt (Stand: 23. Februar 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
Eric Chiang
quelle
2
Der JSON hat eine ganze Menge Verschachtelung. Ich habe versions = [x for x in data["releases"] if any([y["python_version"] in ['cp26', '2.6'] for y in data["releases"][x]])]Versionen gefunden, die mit Python 2.6 kompatibel sind. (Ich habe cp26nirgendwo gesehen, aber einige Pakete hatten, cp27so dass ich spekuliere, dass dies in anderen Paketen existieren könnte.)
Tripleee
2
Hier ist eine Möglichkeit, dies mit Curl, JQ und Sort (einem "Einzeiler"!) Zu tun: 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
Dies löst eine ValueErrorAusnahme für einige Pakete aus, die nicht so strengen Versionsschemata folgen. Informationen zur Behebung dieser Pakete finden Sie in dieser Übersicht .
TrinitronX
veraltet wird dies für Sie tun.
Shadi
18

Ich habe mir ein absolut einfaches Bash-Skript ausgedacht. Vielen Dank an den Autor von 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

Update: Sortierung nach Versionsnummer hinzufügen.

Timofey Stolbov
quelle
Ich konnte nicht zur curlArbeit gehen, möglicherweise aufgrund von Zertifikatfehlern. wget --no-check-certificatefunktioniert, produziert aber auch curl -k --insecurenichts. Die Warnung, die ich mit bekomme, wgetsagtERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
Tripleee
Das sort -Vfunktioniert nicht unter OSX mit Homebrews Version vonjq
deepelement
16

Sie könnten das yolk3k-Paket anstelle von yolk verwenden. yolk3k ist eine Gabel aus dem ursprünglichen Yolk und unterstützt sowohl Python2 als auch 3.

https://github.com/myint/yolk

pip install yolk3k
ykyuen
quelle
Dies war praktisch zu wissen, da Eigelb unter Python 3.x
Broken Man
1
yolk3k gibt nur die installierte Version für mich zurück:yolk -V attest Attest 0.5.3
Antony Hatchkins
2
yolk3k scheint nur die neueste Version zurückzugeben?
Mvherweg
16

Nachdem Sie sich eine Weile den Code von pip angesehen haben, sieht es so aus, als ob der Code, der für das Auffinden von Paketen verantwortlich ist, in der PackageFinderKlasse in zu finden ist pip.index. Die Methode find_requirementsucht nach den Versionen von a InstallRequirement, gibt aber leider nur die neueste Version zurück.

Der folgende Code ist fast eine 1: 1-Kopie der ursprünglichen Funktion, wobei die Rückgabe in Zeile 114 geändert wurde, um alle Versionen zurückzugeben.

Das Skript erwartet einen Paketnamen als erstes und einziges Argument und gibt alle Versionen zurück.

http://pastebin.com/axzdUQhZ

Ich kann die Richtigkeit nicht garantieren, da ich mit dem Code von pip nicht vertraut bin. Aber hoffentlich hilft das.

Beispielausgabe

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

Der 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]
Reiner Gerecke
quelle
Dies funktionierte viel besser als die obige Antwort. Skinny $ Yolk -V Scipy Scipy 0.12.0 Skinny $ Python Test.py Scipy Versionen von 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
Von dieser Verwendung wird in den Dokumenten ausdrücklich abgeraten : " Sie dürfen die internen APIs von pip nicht auf diese Weise verwenden "
wim
9

Mit diesem kleinen Python 3-Skript (das nur Standardbibliotheksmodule verwendet) können Sie die Liste der verfügbaren Versionen für ein Paket von PyPI mithilfe der JSON-API abrufen und in umgekehrter chronologischer Reihenfolge drucken. Im Gegensatz zu einigen anderen hier veröffentlichten Python-Lösungen funktioniert dies nicht bei losen Versionen wie django's 2.2rc1oder 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')

Speichern Sie das Skript und führen Sie es mit dem Paketnamen als Argument aus, z.

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
...
Eugene Yarmash
quelle
7

Dies funktioniert für mich unter OSX:

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

Es gibt die Liste eine pro Zeile zurück:

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

Oder um die neueste Version zu erhalten:

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

Beachten Sie gsort, dass (unter OSX) installiert sein muss, um die Versionen zu analysieren. Sie können es mit installierenbrew install coreutils

Oma
quelle
Herrgott, warum hast du diese Antwort überhaupt gepostet? @ Chris Montaros Antwort funktioniert und ist elegant. Dies führt nur unnötig zu Komplikationen
Brian Leach
@BrianLeach smh ... es ist der gleiche Ansatz gefiltert für die Verwendung in einem Skript ...
Oma
1
Funktioniert in Cygwin / Bash für mich, für die zweite Lösung verwenden Sie sort, nicht gsort in Cygwin.
WebComer
Hier liefert Python wohl einen besser lesbaren Code als bash ... siehe @eric chiang's Antwort (hoffentlich :) oben ...
mirekphd
4

Mein Projekt ludditehat diese Funktion.

Anwendungsbeispiel:

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

Es listet alle verfügbaren Versionen eines Pakets auf, indem die json-API von https://pypi.org/ abgefragt wird.

wim
quelle
Es wäre lehrreicher, wenn Sie uns mitteilen würden, was Ihr Paket tut, andernfalls
bewerben
@ user228395 Ich dachte, es wäre offensichtlich genug, aber es listet alle Versionen eines Pakets auf, die verfügbar sind, und genau darum geht es im Titel der Frage. Bearbeitet - besser?
wim
Es funktioniert natürlich. Es geht also im Wesentlichen darum, die von @Timofey Stolbov vorgestellte Lösung zu verpacken?
user228395
1
@ user228395 Ich würde es nicht "Wrapping" nennen, da diese Antwort bash, curl und jq verwendet - während luddite nur die Python-Standardbibliothek (urllib) verwendet. Die Lösung von Stolbov verwendet jedoch denselben Endpunkt auf pypi.org . Darf ich fragen, was der Grund für Ihre Ablehnung ist?
wim
1
Wenn Sie dem Link zur Projektdetailseite gefolgt sind, können Sie feststellen, dass die Hauptfunktion des Projekts darin besteht, requirements.txtDateien auf veraltete Pakete zu überprüfen . Es sind mehr als ein paar Codezeilen. Um eine requirements.txtDatei zu überprüfen , benötigen Sie die Funktionalität, um alle Paketversionen aufzulisten. Dieser Teil ist absichtlich entkoppelt und Teil der öffentlichen API von luddite. Und es ist die Quelle Apache License 2.0. Ich denke, es ist nicht wirklich fair, das als "Black-Box" -Softwarepaket zu bezeichnen.
wim
2

Ich habe kein Glück mit yolk, yolk3koder pip install -vaber so endete ich dies mit bis (angepasst auf Python 3 von eric Tschiangs Antwort):

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
...
Andrew Magee
quelle
1
StrictVersionnicht für viele Pakete arbeiten ( django, uwsgi, psycopg2um nur einige zu nennen). Sie können parse_version()von verwenden setuptools(siehe meine Antwort für ein Beispiel).
Eugene Yarmash
1

Eine alternative Lösung besteht darin, die Warehouse-APIs zu verwenden:

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

Zum Beispiel für Flask:

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

wird drucken:

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'])
Charlie
quelle
0

Einfaches bashSkript, das sich nur auf sich pythonselbst stützt (ich gehe davon aus, dass es im Kontext der Frage installiert werden sollte) und eines von curloder wget. Es wird davon ausgegangen, dass Sie ein setuptoolsPaket zum Sortieren von Versionen installiert haben (fast immer installiert). Es basiert nicht auf externen Abhängigkeiten wie:

  • jq die möglicherweise nicht vorhanden sind;
  • grepund awkdas kann sich unter Linux und MacOS unterschiedlich verhalten.
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)))"

Eine etwas längere Version mit Kommentaren.

Fügen Sie den Paketnamen in eine Variable ein:

PACKAGE=requests

Versionen abrufen (mit 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)))")

Versionen abrufen (mit 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)))")

Sortierte Versionen drucken:

echo $VERSIONS
Andrey Semakin
quelle
-1

Mein Ansatz ist eine Kombination aus einigen veröffentlichten Antworten mit einigen Änderungen, um die Verwendung in einer laufenden Python-Umgebung zu vereinfachen.

Die Idee ist, einen völlig neuen Befehl (nach dem Vorbild des Installationsbefehls) bereitzustellen, mit dem Sie eine Instanz des zu verwendenden Paketfinders erhalten. Der Vorteil ist, dass es mit allen Indizes funktioniert und diese verwendet, die pip unterstützt und Ihre lokalen Pip-Konfigurationsdateien liest, sodass Sie die richtigen Ergebnisse erhalten, wie Sie es bei einer normalen Pip-Installation tun würden.

Ich habe versucht, es mit pip v 9.x und 10.x kompatibel zu machen, habe es aber nur mit 9.x versucht

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

Beispielausgabe

./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
Kaos
quelle
Von dieser Verwendung wird in den Dokumenten ausdrücklich abgeraten : " Sie dürfen die internen APIs von pip nicht auf diese Weise verwenden. "
wim