2

I need to list all imported modules together with their version. Some of my code only works with specific versions and I want to save the version of the packages, so that I can look it up again in the future. Listing the names of the packages works:

modules = list(set(sys.modules) & set(globals()))
print modules

But if I now want to get the version of the list items it doesn't work with:

for module in modules:
    print module.__version__

Is there a way to address the .__version__ command with a string, or have I to go another way to get the name and the version? In other questions only the names of the modules are addressed: How to list imported modules?

Community
  • 1
  • 1
S. Reich
  • 23
  • 1
  • 7
  • That's because you are saving only the modules *name* in that `modules` list. In any case: note that the `__version__` attribute is just a convention. Many modules don't have that. – Bakuriu Jul 08 '16 at 13:25

2 Answers2

7

Because you have a list of strings of the module name, not the module itself. Try this:

for module_name in modules:
    module = sys.modules[module_name]
    print module_name, getattr(module, '__version__', 'unknown')

Note that not all modules follow the convention of storing the version information in __version__.

wim
  • 338,267
  • 99
  • 616
  • 750
3

One of the issues I have had with huge legacy programs is where aliases have been used (import thing as stuff). It is also often good to know exactly which file is being loaded. I wrote this module a while ago which might do what you need:

spection.py

"""
Python 2 version
10.1.14
"""
import inspect
import sys
import re

def look():

    for name, val in sys._getframe(1).f_locals.items():
        if inspect.ismodule(val):

            fullnm = str(val)

            if not '(built-in)' in fullnm and \
               not __name__     in fullnm:
                m = re.search(r"'(.+)'.*'(.+)'", fullnm)
                module,path = m.groups()
                print "%-12s maps to %s" % (name, path)
                if hasattr(val, '__version__'):
                    print "version:", val.__version__

Using it:

import sys
import matplotlib
import spection

spection.look()

Gives (on my system):

matplotlib   maps to /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/matplotlib/__init__.pyc
version: 1.3.1

You will note that I omit builtins like sys and the spection module itself.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • Great idea! But I would have returned the values as a dictionary, rather than just print them (yes, I know, the OP used print, but in this case it's a utility function)... – SwedishOwlSerpent Aug 14 '17 at 11:02
  • @SwedishOwlSerpent: the original code did just that, I modified it to be closer to the question. It wouldn't take much to change it. – cdarke Aug 15 '17 at 12:11
  • @cdarke this code works only with top level package right? If I import `matplotlib.pyplot` for example, I don't get the matplotlib version. Do you have a current solution working on this? – gc5 May 17 '18 at 16:40
  • @gc5: Not sure if that is feasible since the module being imported is not `matplotlib` but `pyplot`. I have to think on this, I'll post a comment here to you if I get a version working. – cdarke May 18 '18 at 14:54
  • @cdarke Thanks. I actually implemented a small package to do this based on the code provided in this answer (https://stackoverflow.com/a/50396275/41977). The package is `py_session` (https://github.com/fbrundu/py_session). If you can let me know if you find some issues/things we can improve on that. Thanks, – gc5 May 18 '18 at 15:10
  • @gc5 - maybe you should publish it on PyPI ? – cdarke May 18 '18 at 16:09