How to test if a module exists?

Roy Smith roy at panix.com
Sat Nov 6 21:52:35 CET 2010


In article <mailman.699.1289068535.2218.python-list at python.org>,
 Chris Rebert <clp2 at rebertia.com> wrote:

> On Sat, Nov 6, 2010 at 11:22 AM, Jon Dufresne <jon.dufresne at gmail.com> wrote:
[...]
> > However, if the the extension module exists but throws an ImportError,
> > due to a bug in the extension this idiom will mask the error and I
> > will never see it. Later on in the program I will get unexpected
> > behavior because the module never successfully imported. I want the
> > program to fail if the extension module fails to import, but continue
> > if the module doesn't exist. Is there a correct way to handle this?
> 
> Here's what I came up with:
> 
> try:
>     import extension_magic_module
> except ImportError as err:
>     if err.message != "No module named extension_magic_module":
>         raise err
> else:
>     handle_extension_magic_module()

As Mark Wooding pointed out in another post, relying on the text of the 
exception message is a bad idea.

It seems to me that if your module has a bug in it, it's likely to throw 
something other than ImportError, so catching ImportError is probably 
good enough.

On the other hand, if your module's bug is that it in turn imports some 
other module, which doesn't exist, you'll also get an ImportError.  It 
sounds like what you want to do is differentiate between ImportError 
thrown at the top level, and ImportError thrown somewhere deeper in the 
stack.  The best way I can see to do that is to catch ImportError and 
look to see how long the chain of tb_next references is in 
sys.exc_traceback.  If sys.exc_traceback.tb_next is None, the exception 
was thrown at the top level (and your magic module doesn't exist).  
Here's a rough example to illustrate what I'm talking about:

import sys
try:
    import xx
except ImportError:
    tb = sys.exc_traceback
    while tb:
        print tb
        tb = tb.tb_next

It's a little funky, but I think the concept is sound, and it should be 
portable.



More information about the Python-list mailing list