Python: check a package version with importlib.metadata.version()

Artist’s depiction of code riddled with package version checks.

Sometimes, it’s useful to branch the behaviour of your code based on the version of a package that you have installed. This may be to support an upgrade in your project, or for your own package to support different versions of a dependency.

Some Python packages provide a top-level version attribute that gives the version number as a tuple. This is often called __version__, though in the case of Django, it is called django.VERSION, which can be used like this:

import django

if django.VERSION >= (5, 2):
    # Use new features in Django 5.2
    ...
else:
    # Do some backport
    ...

Such version attributes are not a standard though, so not all packages have them. They require extra work from package maintainers to provide: for example, setuptools requires extra dynamic metadata configuration. And in the worst cases, a __version__ attribute may have been forgotten about by new package maintainers, leaving it out of sync with the actual package version.

Instead of using such attributes, you can instead use importlib.metadata.version(), addded in Python 3.8, to get a package version as a string:

In [1]: from importlib.metadata import version

In [2]: version('django')
Out[2]: '5.2.4'

This is available for all installed packages as it reads the metadata files left by the package installer.

For example, the previous example can be rewritten like this:

from importlib.metadata import version

if version("django").startswith("5.2."):
    # Use new features in Django 5.2
    ...
else:
    # Do some backport
    ...

It can be a bit annoying to work with strings, though. In this case, you can install packaging and use its packaging.version.Version class to parse the string into a Version object:

In [1]: from importlib.metadata import version

In [2]: from packaging.version import Version

In [3]: Version(version('django'))
Out[3]: <Version('5.2.4')>

Version objects can be compared with each other, so you can use them like this:

from importlib.metadata import version
from packaging.version import Version

if Version(version("django")) >= Version("5.2"):
    # Use new features in Django 5.2
    ...
else:
    # Do some backport
    ...

Fin

May you never need package-version-branching, and when you do, may it be short-lived.

—Adam


😸😸😸 Check out my new book on using GitHub effectively, Boost Your GitHub DX! 😸😸😸


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: