59

This probably has an obvious answer, but I'm a beginner. I've got a "module" (really just a file with a bunch of functions I often use) at the beginning of which I import a number of other modules. Because I work on many systems, however, not all modules may be able to load on any particular machine. To make things slightly more difficult, I also change the names of the packages when I import them -- for example, matplotlib gets abbreviated to mp.

What I'd like to do is only load those modules that exist on the system I'm currently using, and do some error handling on the ones that don't. The only way I can think of doing so is by enclosing each import statement inside its own try block, which seems pretty un-pythonic. If I enclose them all in the same try block, whichever module throws an error will prevent the subsequent modules from being loaded. Any ideas that might make things look prettier? It would be so easy if I didn't want to change their names...

serv-inc
  • 35,772
  • 9
  • 166
  • 188
Dave Schultz
  • 591
  • 1
  • 4
  • 3
  • 2
    the "imp" module should help you. you might want to read this: http://docs.python.org/library/imp.html – mawimawi Jun 28 '10 at 09:25
  • 2
    @mawimawi : How? Please explain and expand your comment into a proper answer? (I read the doc and it's not obvious why we would want to use that module any more than any other approach) – smci Aug 05 '14 at 20:48

3 Answers3

75

I don't think try except block is un-pythonic; instead it's a common way to handle import on Python.

Quoting Dive into Python:

There are a lot of other uses for exceptions besides handling actual error conditions. A common use in the standard Python library is to try to import a module, and then check whether it worked. Importing a module that does not exist will raise an ImportError exception. You can use this to define multiple levels of functionality based on which modules are available at run-time, or to support multiple platforms (where platform-specific code is separated into different modules).

The next example demonstrates how to use an exception to support platform-specific functionality.

try:
    import termios, TERMIOS                     
except ImportError:
    try:
        import msvcrt                           
    except ImportError:
        try:
            from EasyDialogs import AskPassword 
        except ImportError:
            getpass = default_getpass           
        else:                                   
            getpass = AskPassword
    else:
        getpass = win_getpass
else:
    getpass = unix_getpass
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
systempuntoout
  • 71,966
  • 47
  • 171
  • 241
  • 3
    This is already getting a bit ugly, and will get worse with increasing number of conditional imports in the "chain". It might be viable to use [`importlib.import_module`](https://docs.python.org/3/library/importlib.html#importlib.import_module) in a cycle, eg. iterating over a list of names (`['termios', 'mscvrt', ...]`) until a working module is found. – kyrill Apr 24 '19 at 21:41
  • The link is dead. – Jakuje Dec 03 '20 at 12:55
15

As advocated by https://stackoverflow.com/a/20228312/1587329 [modified, with an edit from @Ian]

from importlib import import_module

named_libs = [('numpy', 'np'), ('matplotlib', 'mp')] # (library_name, shorthand)
for (name, short) in named_libs:
    try:
        lib = import_module(name)
    except:
        print(sys.exc_info())
    else:
        globals()[short] = lib

imports all libraries in named_libs. The first string is the library name, the second the shorthand. For unnamed libraries, you can use the original:

from importlib import import_module     

libnames = ['numpy', 'scipy', 'operator']
for libname in libnames:
    try:
        lib = import_module(libname)
    except:
        print(sys.exc_info())
    else:
        globals()[libname] = lib
blong
  • 2,815
  • 8
  • 44
  • 110
serv-inc
  • 35,772
  • 9
  • 166
  • 188
  • 1
    Extra context for other beginner Python folks like me, from [Serious Python](https://nostarch.com/seriouspython): "[T]he `import` keyword is actually a wrapper around a function named `__import__()`" – DukeSilver Mar 28 '19 at 16:11
5

The easiest way is to ensure that all modules can be loaded on all systems. If that doesn't work, enclosing each import statement in a try block is the next best solution and not un-Pythonic at all.

Philipp
  • 48,066
  • 12
  • 84
  • 109