430 Stimmen

Wie kann ich Versionsnummern in Python vergleichen?

Ich gehe durch ein Verzeichnis, das Eier enthält, um diese Eier zu den sys.path . Wenn es zwei Versionen desselben .egg im Verzeichnis gibt, möchte ich nur die neueste hinzufügen.

Ich habe einen regulären Ausdruck r"^(?P<eggName>\w+)-(?P<eggVersion>[\d\.]+)-.+\.egg$ um den Namen und die Version aus dem Dateinamen zu extrahieren. Das Problem besteht darin, die Versionsnummer zu vergleichen, die eine Zeichenkette ist wie 2.3.1 .

Da ich Zeichenketten vergleiche, wird 2 über 10 sortiert, aber das ist für Versionen nicht korrekt.

>>> "2.3.1" > "10.1.1"
True

Ich könnte einige Splitting, Parsing, Casting zu int, etc. tun, und ich würde schließlich eine Problemlösung zu bekommen. Aber das ist Python, nicht Java . Gibt es eine elegante Möglichkeit, Versionszeichenfolgen zu vergleichen?

0voto

nairoby Punkte 57

... und zurück zu easy ... für einfache Skripte, die Sie verwenden können:

import sys
needs = (3, 9) # or whatever
pvi = sys.version_info.major, sys.version_info.minor    

später in Ihrem Code

try:
    assert pvi >= needs
except:
    print("will fail!")
    # etc.

0voto

Abanoub Hany Punkte 386

So erhöhen Sie die Version mit Python

def increment_version(version):
    version = version.split('.')
    if int(version[len(version) - 1]) >= 99:
        version[len(version) - 1] = '0'
        version[len(version) - 2] = str(int(version[len(version) - 2]) + 1)
    else:
        version[len(version) - 1] = str(int(version[len(version) - 1]) + 1)
    return '.'.join(version)

version = "1.0.0"
version_type_2 = "1.0"
print("old version",version ,"new version",increment_version(version))
print("old version",version_type_2 ,"new version",increment_version(version_type_2))

0voto

Dies ist ein kompakter Code für den Vergleich von drei Versionsnummern. Beachten Sie, dass der String-Vergleich hier für alle Paare fehlschlägt.

from itertools import permutations

for v1, v2 in permutations(["3.10.21", "3.10.3", "3.9.9"], 2):
    print(f"\nv1 = {v1}, v2 = {v2}")
    print(f"v1 < v2      version.parse(v1) < version.parse(v2)")
    print(f"{v1 < v2}         {version.parse(v1) < version.parse(v2)}")

Das gibt uns:

v1='3.10.21', v2='3.10.3'
v1 < v2      version.parse(v1) < version.parse(v2)
True         False

v1='3.10.21', v2='3.9.9'
v1 < v2      version.parse(v1) < version.parse(v2)
True         False

v1='3.10.3', v2='3.10.21'
v1 < v2      version.parse(v1) < version.parse(v2)
False         True

v1='3.10.3', v2='3.9.9'
v1 < v2      version.parse(v1) < version.parse(v2)
True         False

v1='3.9.9', v2='3.10.21'
v1 < v2      version.parse(v1) < version.parse(v2)
False         True

v1='3.9.9', v2='3.10.3'
v1 < v2      version.parse(v1) < version.parse(v2)
False         True

permutations(iterable, 2) gibt uns alle 2-Längen Permutationen einer Iterablen. Also zum Beispiel

list(permutations('ABC', 2))

gibt uns [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')] .

-1voto

Muayyad Alsadi Punkte 1408

Ähnlich dem Standard strverscmp und ähnlich wie diese Lösung von Mark Byers aber mit findall anstelle von split, um leere Fälle zu vermeiden.

import re
num_split_re = re.compile(r'([0-9]+|[^0-9]+)')

def try_int(i, fallback=None):
    try:
        return int(i)
    except ValueError:
        pass
    except TypeError:
        pass
    return fallback

def ver_as_list(a):
    return [try_int(i, i) for i in num_split_re.findall(a)]

def strverscmp_lt(a, b):
    a_ls = ver_as_list(a)
    b_ls = ver_as_list(b)
    return a_ls < b_ls

-1voto

Justin Punkte 699

Hier ist etwas, das funktionieren wird, vorausgesetzt, Ihre semantischen Versionen sind "sauber" (z. B. x.x.x ) und Sie haben eine Liste von Versionen, die Sie sortieren müssen.

# Here are some versions
versions = ["1.0.0", "1.10.0", "1.9.0"]

# This does not work
versions.sort() # Result: ['1.0.0', '1.10.0', '1.9.0']

# So make a list of tuple versions
tuple_versions = [tuple(map(int, (version.split(".")))) for version in versions]

# And sort the string list based on the tuple list
versions = [x for _, x in sorted(zip(tuple_versions, versions))] # Result: ['1.0.0', '1.9.0', '1.10.0']

Um die neueste Version zu erhalten, können Sie einfach das letzte Element in der Liste auswählen versions[-1] oder umgekehrt sortieren, indem Sie die reverse Attribut von sorted() und setzen ihn auf True und der Erhalt der [0] Element.

Natürlich können Sie all dies in eine praktische Funktion zur Wiederverwendung verpacken.

def get_latest_version(versions):
    """
    Get the latest version from a list of versions.
    """
    try:
        tuple_versions = [tuple(map(int, (version.split(".")))) for version in versions]
        versions = [x for _, x in sorted(zip(tuple_versions, versions), reverse=True)]
        latest_version = versions[0]
    except Exception as e:
        print(e)
        latest_version = None

    return latest_version

print(get_latest_version(["1.0.0", "1.10.0", "1.9.0"]))

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X