44

I looked at python-apt and python-debian, and they don't seem to have functionality to compare package versions. Do I have to write my own, or is there something I can use?

Ideally, it would look something like:

>>> v1 = apt.version("1:1.3.10-0.3")
>>> v2 = apt.version("1.3.4-1")
>>> v1 > v2
True
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
tshepang
  • 12,111
  • 21
  • 91
  • 136

4 Answers4

76

Perhaps because the title doesn't mention Python (though the tags do), Google brought me here when asking the same question but hoping for a bash answer. That seems to be:

$ dpkg --compare-versions 11a lt 100a && echo true
true
$ dpkg --compare-versions 11a gt 100a && echo true
$ 

To install a version of rubygems that's at least as new as the version from lenny-backports in a way that gives no errors on lenny and squeeze installations:

sudo apt-get install rubygems &&
VERSION=`dpkg-query --show --showformat '${Version}' rubygems` &&
dpkg --compare-versions $VERSION lt 1.3.4-1~bpo50+1 &&
sudo apt-get install -t lenny-backports rubygems

Perhaps I should have asked how to do that in a separate question, in the hope of getting a less clunky answer.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Martin Dorey
  • 2,944
  • 2
  • 24
  • 16
  • 2
    For info, for Python in 2021, this is the best solution. There are a lot of Debian versions format not supported by the lib mentioned in other answsers. Making a Python function that call the bash command in this answers works like a charm. `return subprocess.call(['dpkg', '--compare-versions', '11a', 'gt', '100a']) == 0` – Pierre Jan 25 '21 at 16:03
  • @PierreF "best" is subjective in this context. This code will only run on a debian fork version of linux. There's various contexts, including CI pipelines where you may want to compare Debian versions and not have `dpkg` available. – Philip Couling May 27 '22 at 11:23
47

You could use apt_pkg.version_compare:

import apt_pkg
apt_pkg.init_system()

a = '1:1.3.10-0.3'
b = '1.3.4-1'
vc = apt_pkg.version_compare(a,b)
if vc > 0:
    print('version a > version b')
elif vc == 0:
    print('version a == version b')
elif vc < 0:
    print('version a < version b')        

yields

version a > version b

Thanks to Tshepang for noting in the comments that for newer versions: apt.VersionCompare is now apt_pkg.version_compare.

Starfish
  • 1,083
  • 10
  • 23
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • I guess your packager installed it in a different place. I found it [here](http://apt.alioth.debian.org/python-apt-doc/library/apt_pkg.html#apt_pkg.version_compare). And that's about the same place I fin mine also. I also think you have an old version of python-apt because they are moving away from CamelCase, and I guess that's why it isn't documented. – tshepang Feb 10 '11 at 14:16
  • @Tshepang: Indeed, my python-apt is pretty old. Thanks for the update – unutbu Feb 10 '11 at 15:29
  • Actually, your code works fine. The developers were prudent enough to keep it as some sort of alias for newer method names. – tshepang Feb 10 '11 at 15:36
  • 3
    Also, `apt.version_compare` doesn't work. Use `apt_pkg.version_compare` instead. – tshepang Feb 11 '11 at 11:52
  • I end up with `ValueError: _system not initialized` if I use `apt_pkg.version_compare()`. – Nathan Osman Feb 11 '16 at 05:16
  • @NathanOsman: My mistake. The code above was missing a call to `apt_pkg.init_system()`. See http://unix.stackexchange.com/q/172311/3330. – unutbu Feb 11 '16 at 12:09
  • links are dead. try https://apt-team.pages.debian.net/python-apt/library/apt_pkg.html#apt_pkg.version_compare – milahu Apr 19 '23 at 12:28
8

python-debian can do this too. It's used in an almost identical way to python-apt:

from debian import debian_support 

a = '1:1.3.10-0.3'
b = '1.3.4-1'
vc = debian_support.version_compare(a,b)
if vc > 0:
    print('version a > version b')
elif vc == 0:
    print('version a == version b')
elif vc < 0:
    print('version a < version b')

ouput:

version a > version b
Jeremy Davis
  • 741
  • 10
  • 16
  • 2
    Answer appreciated especially because it doesn't require installing apt_pkg which can be problematic sometimes. python-debian seems to have a fallback mode that implements the version comparison by itself. – Eran Jan 11 '21 at 12:46
3

As you already mentioned python-apt and python-debian, but it is 2022 by now and Python 2.7 is end-of-life, here's the Python 3 code for a Debian based system, where you have installed python3-debian:

from debian.debian_support import Version
v1 = Version("1:1.3.10-0.3")
v2 = Version("1.3.4-1")
print(v1 > v2)

python3-debian will automatically used the more efficient version from python3-apt if it is installed. But you also can use it explicitly by importing Version from apt:

from apt import Version
pmhahn
  • 101
  • 3