Je marche dans un répertoire qui contient des œufs pour ajouter ces œufs à la sys.path
. S'il existe deux versions du même .egg dans le répertoire, je souhaite ajouter uniquement la dernière.
J'ai une expression régulière r"^(?P<eggName>\w+)-(?P<eggVersion>[\d\.]+)-.+\.egg$
pour extraire le nom et la version du nom de fichier. Le problème est de comparer le numéro de version, qui est une chaîne comme 2.3.1
.
Puisque je compare des chaînes, 2 sortes au-dessus de 10, mais ce n'est pas correct pour les versions.
>>> "2.3.1" > "10.1.1"
True
Je pourrais faire un fractionnement, une analyse, un cast en int, etc., et j'obtiendrais finalement une solution de contournement. Mais c'est Python, pas Java . Existe-t-il un moyen élégant de comparer les chaînes de version?
la source
distutils.version
est sans papiers.version.py
code source. Très bien mis!packaging.version.parse
ne peut pas faire confiance pour comparer les versions. Essayezparse('1.0.1-beta.1') > parse('1.0.0')
par exemple.La bibliothèque d' empaquetage contient des utilitaires pour travailler avec des versions et d'autres fonctionnalités liées à l'empaquetage. Cela implémente PEP 0440 - Identification de version et est également capable d'analyser les versions qui ne suivent pas le PEP. Il est utilisé par pip et d'autres outils Python courants pour fournir l'analyse et la comparaison des versions.
Cela a été séparé du code d'origine dans setuptools et pkg_resources pour fournir un package plus léger et plus rapide.
Avant que la bibliothèque d'empaquetage n'existe, cette fonctionnalité était (et peut toujours être) trouvée dans pkg_resources, un paquet fourni par setuptools. Cependant, cela n'est plus préféré car setuptools n'est plus garanti d'être installé (d'autres outils de packaging existent), et pkg_resources utilise ironiquement beaucoup de ressources lors de l'importation. Cependant, tous les documents et discussions sont toujours pertinents.
De la
parse_version()
documentation :L '"algorithme d'origine" référencé a été défini dans les anciennes versions de la documentation, avant l'existence du PEP 440.
La documentation fournit quelques exemples:
la source
la source
map()
complètement la fonction, car le résultat desplit()
est déjà des chaînes. Mais vous ne voulez pas le faire de toute façon, car toute la raison de les changerint
est pour qu'ils se comparent correctement en tant que nombres. Sinon"10" < "2"
.versiontuple("1.0") > versiontuple("1")
. Les versions sont les mêmes, mais les tuples créés(1,)!=(1,0)
distutils.version.LooseVersion
. C'est pour ça qu'il est là.Qu'y a-t-il de mal à transformer la chaîne de version en un tuple et à partir de là? Semble assez élégant pour moi
La solution de @ kindall est un exemple rapide de l'apparence du code.
la source
setuptools
, ce qui estpkg_resources
.pkg_resources
, et que les hypothèses de nommage simple des packages ne sont pas toujours idéales.sys.version_info > (3, 6)
ou autre chose.Un emballage est disponible, ce qui vous permettra de comparer les versions selon PEP-440 , ainsi que les versions héritées.
Prise en charge des versions héritées:
Comparaison de la version héritée avec la version PEP-440.
la source
packaging.version.Version
etpackaging.version.parse
: "[version.parse
] prend une chaîne de version et l'analysera comme unVersion
si la version est une version PEP 440 valide, sinon il l'analysera comme unLegacyVersion
." (alorsversion.Version
qu'il augmenteraitInvalidVersion
; source )Vous pouvez utiliser le package semver pour déterminer si une version satisfait une exigence de version sémantique . Ce n'est pas la même chose que de comparer deux versions réelles, mais c'est un type de comparaison.
Par exemple, la version 3.6.0 + 1234 devrait être la même que la version 3.6.0.
la source
Publier ma fonction complète basée sur la solution de Kindall. J'ai pu prendre en charge tous les caractères alphanumériques mélangés aux chiffres en remplissant chaque section de version avec des zéros en tête.
Bien que certainement pas aussi joli que sa fonction à une ligne, il semble bien fonctionner avec les numéros de version alphanumériques. (Assurez-vous simplement de définir la
zfill(#)
valeur de manière appropriée si vous avez de longues chaînes dans votre système de gestion des versions.).
la source
La façon dont
setuptools
il le fait, il utilise lapkg_resources.parse_version
fonction. Ce devrait être PEP440 conforme au .Exemple:
la source
pkg_resources
fait partie desetuptools
, qui dépendpackaging
. Voir les autres réponses qui discutentpackaging.version.parse
, qui a une implémentation identique àpkg_resources.parse_version
.Je cherchais une solution qui n'ajouterait aucune nouvelle dépendance. Découvrez la solution suivante (Python 3):
EDIT: variante ajoutée avec comparaison de tuple. Bien sûr, la variante avec comparaison de tuple est plus agréable, mais je cherchais la variante avec comparaison entière
la source