How do I get the version of an installed module in Python programmatically?

Question:

For the modules:

required_modules = ['nose', 'coverage', 'webunit', 'MySQLdb', 'pgdb', 'memcache']

and programs:

required_programs = ['psql', 'mysql', 'gpsd', 'sox', 'memcached']

Something like:

# Report on the versions of programs installed
for module in required_modules:
    try:
        print module.__version__
    except:
        exit
Asked By: kamal

||

Answers:

Unfortunately, module.__version__ isn’t present in all modules.

A workaround is to use a package manager. When you install a library using easy_install or pip, it keeps a record of the installed version. Then you can do:

import pkg_resources
version = pkg_resources.get_distribution("nose").version
Answered By: moraes

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

Version numbers in python can be in very different places depending on the case:

  • for modules and packages, on the optional __version__ attribute as recommended by PEP396. It should be considered inherited by subpackages and submodules by default if they do not have the attribute.

  • for distributed modules and packages, on the Version Metadata field as indicated by PEP345, that is located:

    • for built wheels distributions (PEP427), on the dist-info directory, but also in the dist-info folder name
    • for built eggs distributions (legacy format from setuptools), on the egg-info directory, but is also in the egg-info folder name
  • finally, for built-in modules and packages, the default version should be inherited from the python system version except if overridden

In addition to this, at runtime (when you need that version number), packages and modules can be

  • already imported or not
  • built and pip-installed (in debug mode or not), or simply added to the PYTHON PATH (sys.path)
  • non-built and added to the PYTHON PATH (sys.path)

This variety of settings makes it very difficult for existing solutions to tackle all aspects of this problem. pkg_resources is probably the best way to get it as of today, but does not work for example when a package is an unzipped wheel added to the PYTHON PATH. It also does not support built-in modules.

Since we needed a reliable way to get the version of any package, module or submodule, I ended up writing getversion. It implements a series of strategies in sequence, until something works.

It is quite simple to use:

from getversion import get_module_version

# Get the version of an imported module
from xml import dom
version, details = get_module_version(dom)

In particular the details provide useful hints about how the version flag was retrieved:

> print(details)
Version '3.7.3.final.0' found for module 'xml.dom' by strategy 'get_builtin_module_version', after the following failed attempts:
 - Attempts for module 'xml.dom':
   - <get_module_version_attr>: module 'xml.dom' has no attribute '__version__'
 - Attempts for module 'xml':
   - <get_module_version_attr>: module 'xml' has no attribute '__version__'
   - <get_version_using_pkgresources>: Invalid version number: None
   - <get_builtin_module_version>: SUCCESS: 3.7.3.final.0

See the documentation for details. I copied the above details about the problem from this page.

Answered By: smarie
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.