147

Many third-party Python modules have an attribute which holds the version information for the module (usually something like module.VERSION or module.__version__), however some do not.

Particular examples of such modules are libxslt and libxml2.

I need to check that the correct version of these modules are being used at runtime. Is there a way to do this?

A potential solution wold be to read in the source at runtime, hash it, and then compare it to the hash of the known version, but that's nasty.

Is there a better solutions?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gruff
  • 1,748
  • 2
  • 13
  • 8
  • Does this answer your question? [How do I check the versions of Python modules?](https://stackoverflow.com/questions/20180543/how-do-i-check-the-versions-of-python-modules) – Jakub Kukul Jul 27 '22 at 16:15

7 Answers7

269

Use pkg_resources. Anything installed from PyPI at least should have a version number.

>>> import pkg_resources
>>> pkg_resources.get_distribution("blogofile").version
'0.7.1'
sid16rgt
  • 736
  • 5
  • 14
EnigmaCurry
  • 5,597
  • 2
  • 23
  • 15
  • 8
    Also note that, package name must be that of PyPI entry. So something like "pkg_resources.get_distribution('MySQLdb').version" won't work but "pkg_resources.get_distribution('mysql-python').version" will. – Rahul Aug 21 '12 at 08:17
  • 1
    If you are running with an absolute file name, `pkg_resources` might pick up a different version shadowing the one you are actually running because it has higher precedence on your `PYTHONPATH` or similar. – tripleee Feb 12 '14 at 10:58
  • 4
    In case somebody wants to know how to make the `__version__` attribute: http://stackoverflow.com/q/17583443/562769 – Martin Thoma Oct 07 '14 at 14:08
  • `pkg_resources` link is an Error 404 – gerrit Nov 22 '19 at 16:00
  • For automated processing, see [this question](https://stackoverflow.com/q/11887762/974555) – gerrit Nov 22 '19 at 16:03
  • 1
    This unfortunately has quite a lot of limitations. See https://stackoverflow.com/a/56910431/7262247 – smarie Jan 29 '20 at 17:19
  • [DeprecationWarning: pkg_resources is deprecated as an API](https://github.com/pypa/setuptools/blob/main/NEWS.rst#changes-4). – wim Jul 20 '23 at 05:01
28

If you're on python >=3.8 you can use a module from the built-in library for that. To check a package's version (in this example lxml) run:

>>> from importlib.metadata import version
>>> version('lxml')
'4.3.1'

This functionality has been ported to older versions of python (<3.8) as well, but you need to install a separate library first:

pip install importlib_metadata

and then to check a package's version (in this example lxml) run:

>>> from importlib_metadata import version
>>> version('lxml')
'4.3.1'

Keep in mind that this works only for packages installed from PyPI. Also, you must pass a package name as an argument to the version method, rather than a module name that this package provides (although they're usually the same).

Jakub Kukul
  • 12,032
  • 3
  • 54
  • 53
8

I'd stay away from hashing. The version of libxslt being used might contain some type of patch that doesn't effect your use of it.

As an alternative, I'd like to suggest that you don't check at run time (don't know if that's a hard requirement or not). For the python stuff I write that has external dependencies (3rd party libraries), I write a script that users can run to check their python install to see if the appropriate versions of modules are installed.

For the modules that don't have a defined 'version' attribute, you can inspect the interfaces it contains (classes and methods) and see if they match the interface they expect. Then in the actual code that you're working on, assume that the 3rd party modules have the interface you expect.

jldupont
  • 93,734
  • 56
  • 203
  • 318
Mark Roddy
  • 27,122
  • 19
  • 67
  • 71
6

Some ideas:

  1. Try checking for functions that exist or don't exist in your needed versions.
  2. If there are no function differences, inspect function arguments and signatures.
  3. If you can't figure it out from function signatures, set up some stub calls at import time and check their behavior.
Richard Levasseur
  • 14,562
  • 6
  • 50
  • 63
  • Packages should specify their version. These ideas are totally overkill for the usually (estimated 99% of the cases) easy task of checking a version. – Zelphir Kaltstahl Apr 30 '19 at 09:47
3

I found it quite unreliable to use the various tools available (including the best one pkg_resources mentioned by this other answer), as most of them do not cover all cases. For example

  • built-in modules
  • modules not installed but just added to the python path (by your IDE for example)
  • two versions of the same module available (one in python path superseding the one installed)

Since we needed a reliable way to get the version of any package, module or submodule, I ended up writing getversion. It is quite simple to use:

from getversion import get_module_version
import foo
version, details = get_module_version(foo)

See the documentation for details.

smarie
  • 4,568
  • 24
  • 39
1

You can use

pip freeze

to see the installed packages in requirements format.

nos
  • 19,875
  • 27
  • 98
  • 134
0

For modules which do not provide __version__ the following is ugly but works:

#!/usr/bin/env python3.6
import sys
import os
import subprocess
import re

sp = subprocess.run(["pip3", "show", "numpy"], stdout=subprocess.PIPE)
ver = sp.stdout.decode('utf-8').strip().split('\n')[1]
res = re.search('^Version:\ (.*)$', ver)
print(res.group(1))

or

#!/usr/bin/env python3.7
import sys
import os
import subprocess
import re

sp = subprocess.run(["pip3", "show", "numpy"], capture_output=True)
ver = sp.stdout.decode('utf-8').strip().split('\n')[1]
res = re.search('^Version:\ (.*)$', ver)
print(res.group(1))
phzx_munki
  • 1,058
  • 11
  • 16