Fix Python – How do I compare version numbers in Python?

Question

Asked By – BorrajaX

I am walking a directory that contains eggs to add those eggs to the sys.path. If there are two versions of the same .egg in the directory, I want to add only the latest one.

I have a regular expression r"^(?P<eggName>\w+)-(?P<eggVersion>[\d\.]+)-.+\.egg$ to extract the name and version from the filename. The problem is comparing the version number, which is a string like 2.3.1.

Since I’m comparing strings, 2 sorts above 10, but that’s not correct for versions.

>>> "2.3.1" > "10.1.1"
True

I could do some splitting, parsing, casting to int, etc., and I would eventually get a workaround. But this is Python, not Java. Is there an elegant way to compare version strings?

Now we will see solution for issue: How do I compare version numbers in Python?


Answer

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 is a third-party utility but is used by setuptools (so you probably already have it installed) and is conformant to the current PEP 440; it will return a packaging.version.Version if the version is compliant and a packaging.version.LegacyVersion if not. The latter will always sort before valid versions.

Note: packaging has recently been vendored into setuptools.


An ancient and now deprecated method you might encounter is distutils.version, it’s undocumented and conforms only to the superseded PEP 386;

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

As you can see it sees valid PEP 440 versions as “not strict” and therefore doesn’t match modern Python’s notion of what a valid version is.

As distutils.version is undocumented, here are the relevant docstrings.

This question is answered By – ecatmur

This answer is collected from stackoverflow and reviewed by FixPython community admins, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0