Use packaging.version.parse
.
>>> from packaging import version
>>> version.parse("2.3.1") < version.parse("10.1.2")
True
>>> version.parse("1.3.a4") < version.parse("10.1.2")
True
>>> isinstance(version.parse("1.3.a4"), version.Version)
True
>>> isinstance(version.parse("1.3.xy123"), version.LegacyVersion)
True
>>> version.Version("1.3.xy123")
Traceback (most recent call last):
...
packaging.version.InvalidVersion: Invalid version: '1.3.xy123'
packaging.version.parse
é um utilitário de terceiros, mas é usado pelo setuptools (então você provavelmente já o instalou) e está em conformidade com o PEP 440 atual ; retornará a packaging.version.Version
se a versão for compatível e a packaging.version.LegacyVersion
se não for. O último sempre será classificado antes das versões válidas.
Nota : a embalagem foi vendida recentemente em setuptools .
Uma alternativa antiga ainda usada por muitos softwares é distutils.version
incorporada, mas não documentada e compatível apenas com o PEP 386 substituído ;
>>> from distutils.version import LooseVersion, StrictVersion
>>> LooseVersion("2.3.1") < LooseVersion("10.1.2")
True
>>> StrictVersion("2.3.1") < StrictVersion("10.1.2")
True
>>> StrictVersion("1.3.a4")
Traceback (most recent call last):
...
ValueError: invalid version number '1.3.a4'
Como você pode ver, vê versões válidas do PEP 440 como "não rigorosas" e, portanto, não corresponde à noção moderna do Python sobre o que é uma versão válida.
Como não distutils.version
está documentado, aqui estão os documentos relevantes.
distutils.version
não documentada.version.py
código-fonte. Muito bem colocado!packaging.version.parse
não pode ser confiável para comparar versões. Tenteparse('1.0.1-beta.1') > parse('1.0.0')
por exemplo.A biblioteca de embalagens contém utilitários para trabalhar com versões e outras funcionalidades relacionadas a embalagens. Isso implementa o PEP 0440 - Identificação da versão e também é capaz de analisar versões que não seguem o PEP. É usado pelo pip e outras ferramentas comuns do Python para fornecer análise e comparação de versões.
Isso foi separado do código original em setuptools e pkg_resources para fornecer um pacote mais leve e mais rápido.
Antes da biblioteca de empacotamento existir, essa funcionalidade era (e ainda pode ser) encontrada em pkg_resources, um pacote fornecido pelo setuptools. No entanto, isso não é mais preferido, pois não é mais garantido que o setuptools seja instalado (outras ferramentas de empacotamento existem) e o pkg_resources ironicamente usa muitos recursos quando importado. No entanto, todos os documentos e discussões ainda são relevantes.
Dos
parse_version()
documentos :O "algoritmo original" mencionado foi definido em versões mais antigas dos documentos, antes da existência do PEP 440.
A documentação fornece alguns exemplos:
fonte
fonte
map()
completamente a função, pois o resultado jásplit()
é de strings. Mas você não quer fazer isso de qualquer maneira, porque todo o motivo para alterá-los é para que eles sejam comparados corretamente como números. Caso contrário .int
"10" < "2"
versiontuple("1.0") > versiontuple("1")
. As versões são as mesmas, mas as tuplas criado(1,)!=(1,0)
distutils.version.LooseVersion
. É para isso que serve.O que há de errado em transformar a string de versão em uma tupla e partir daí? Parece elegante o suficiente para mim
A solução da @ kindall é um exemplo rápido de quão bom o código seria.
fonte
setuptools
, o que épkg_resources
.pkg_resources
, e que suposições de nomes simples de pacotes nem sempre podem ser ideais.sys.version_info > (3, 6)
ou o que quer.Há um pacote de embalagem disponível, que permitirá comparar versões conforme PEP-440 , bem como versões herdadas.
Suporte à versão herdada:
Comparando a versão herdada com a versão PEP-440.
fonte
packaging.version.Version
epackaging.version.parse
: "[version.parse
] pega uma string de versão e a analisa comoVersion
se a versão for uma versão válida do PEP 440, caso contrário, ela será analisada como aLegacyVersion
." (enquanto queversion.Version
elevariaInvalidVersion
; source )Você pode usar o pacote semver para determinar se uma versão atende a um requisito de versão semântica . Não é o mesmo que comparar duas versões reais, mas é um tipo de comparação.
Por exemplo, a versão 3.6.0 + 1234 deve ser a mesma que 3.6.0.
fonte
Publicando minha função completa com base na solução de Kindall. Consegui suportar qualquer caractere alfanumérico misturado com os números preenchendo cada seção da versão com zeros à esquerda.
Embora certamente não seja tão bonito quanto sua função de uma linha, parece funcionar bem com números de versão alfanuméricos. (Apenas certifique-se de definir o
zfill(#)
valor adequadamente se você tiver longas seqüências de caracteres em seu sistema de controle de versão.).
fonte
Da maneira que
setuptools
faz isso, ele usa apkg_resources.parse_version
função Deve ser PEP440 compatível com .Exemplo:
fonte
pkg_resources
faz parte dosetuptools
qual dependepackaging
. Veja outras respostas que discutempackaging.version.parse
, com uma implementação idêntica àpkg_resources.parse_version
.Eu estava procurando uma solução que não adicionasse novas dependências. Confira a seguinte solução (Python 3):
EDIT: variante adicionada com comparação de tupla. Claro que a variante com comparação de tupla é melhor, mas eu estava procurando a variante com comparação de números inteiros
fonte