Brian M. Hunt
Brian M. Hunt

Reputation: 83818

Test for Python module dependencies being installed

How could one test whether a set of modules is installed, given the names of the modules. E.g.

modules = set(["sys", "os", "jinja"])

for module in modules:
  # if test(module exists):
  #   do something

While it's possible to write out the tests as:

try:
  import sys
except ImportError:
  print "No sys!"

This is a bit cumbersome for what I'm doing. Is there a dynamic way to do this?

I've tried eval("import %s"%module) but that complained of a compile error.

I'm grateful for your thoughts and suggestions. Thank you.

Upvotes: 7

Views: 4084

Answers (4)

slinkp
slinkp

Reputation: 3606

It's worth understanding the tradeoffs between the find_module approach and the __import__ approach:

  • __import__('foo') will trigger any side effects of loading the module, regardless of whether you save a reference to the imported module. That might be OK, or not.
  • find_module('foo') won't trigger any side effects, so it should always be safe.
  • neither approach works well if the module is found but has other problems at load time (eg. SyntaxError, NameError, ...)
  • Depending on how you handle failures, simply wrapping __import__('foo') in a try/except will give you misleading results if foo is found but foo imports bar which is not found.
  • find_module() can't handle dotted names, so if you need to check whether 'foo.bar.bat.baz' can be imported, you have to use multiple calls to find_module and load_module as per the docs.

Upvotes: 5

vartec
vartec

Reputation: 134611

modules = set(["sys", "os", "jinja"])
try:
  for module in modules:
    __import__(module)
  doSomething()
except ImportError, e:
    print e

Upvotes: 2

Rick Copeland
Rick Copeland

Reputation: 11912

You can use the __import__() function like this::

for module in modules:
    try:
        __import__(module)
    except ImportError:
        do_something()

You can also use imp.find_module to determine whether a module can be found without importing it::

import imp
for module in modules:
    try:
        imp.find_module(module)
    except ImportError:
        do_something()

Oh, and the reason you can't use eval() is because import is a statement, not an expression. You can use exec if you really want to, though I wouldn't recommend it::

for module in modules:
    try:
        exec 'import ' + module
    except ImportError:
        do_something()

Upvotes: 8

Paolo Bergantino
Paolo Bergantino

Reputation: 488454

What's wrong with this?

modules = set(["sys", "os", "jinja"])
for m in modules:
    try:
        __import__(m)
    except ImportError:
        # do something

The above uses the __import__ function. Also, it is strictly testing whether it exists or not - its not actually saving the import anywhere, but you could easily modify it to do that.

Upvotes: 6

Related Questions