8

I would like to import bunch of libraries and catch the exception.

If I have only 1 try catch block I get 1 exception (the first one). Is there a pattern to iterate over all of the libs and have a separate exception for each individual missing lib?

#!/usr/bin/env python

try: import sys
except: print sys.exc_info()
try: import numpy as np
except: print sys.exc_info()
try: import scipy as sp
except: print sys.exc_info()
try: import os as os
except: print sys.exc_info()
try: from operator import itemgetter
except: print sys.exc_info()
try: import socket
except: print sys.exc_info()
try: import logging
except: print sys.exc_info()
try: from time import gmtime, strftime
except: print sys.exc_info()
serv-inc
  • 35,772
  • 9
  • 166
  • 188
Istvan
  • 7,500
  • 9
  • 59
  • 109
  • 10
    Your exception handler will fail entirely if importing `sys` fails. – Martijn Pieters Nov 26 '13 at 19:36
  • 7
    I'd leave out the standard libraries here. Why would importing those fail *at all*? – Martijn Pieters Nov 26 '13 at 19:37
  • 4
    And why should your code work at all if any of these imports fail? Is your code robust enough to handle `sp` or `np` not being defined? – Martijn Pieters Nov 26 '13 at 19:37
  • 1
    This is all a bit pointless as Martijn rightly pointed out. But if you do insist for whatever reason don't use previously imported modules in subsequent lines (e.g. `sys`) because they may not have been imported. – Aleksander Lidtke Nov 26 '13 at 19:41
  • 2
    I disagree with the commenters here - There are valid use cases. You may run embedded Python (as inside an app, or embedded device) with crippled run-time and I have encounter such bastards e.g. on Nokia Series 60 mobile phones. R.I.P. However in this the handling is only used to find out WHY your app is crashing on an embedded device, as often the standard error handler simply does not output anything. – Mikko Ohtamaa Nov 26 '13 at 20:10

3 Answers3

13

You can use __import__ to dynamically import modules, allowing you to - among other things - import modules by iterating a list with their names.

For example:

libnames = ['numpy', 'scipy', 'operator']
for libname in libnames:
    try:
        lib = __import__(libname)
    except:
        print(sys.exc_info())
    else:
        globals()[libname] = lib

You can either extend that to handle the import ... as ... and from ... import ... forms or just do the assignments later manually, ie.:

np = numpy
sp = scipy
itemgetter = operator.itemgetter
blong
  • 2,815
  • 8
  • 44
  • 110
Aleksi Torhamo
  • 6,452
  • 2
  • 34
  • 44
  • 3
    I like this solution better because it uses basic python without the need of importing extra libraries. – Istvan Dec 06 '13 at 23:36
8

Though common, the following easy design pattern and its variations are discouraged:

  # BAD, hides circular import etc. nested errors 
  try:
       import moolib
  except ImportError:
       raise ImportError("You must install moolib from http://moo.example.com in order to run this app")

Instead use the Python package manager to check if a libray is available:

# GOOD
import pkg_resources

try:
    pkg_resources.get_distribution('plone.dexterity')
except pkg_resources.DistributionNotFound:
    HAS_DEXTERITY = False
else:
    HAS_DEXTERITY = True

More about the topic can be found here

As the comments above point out, Python standard library modules (stdlib) are always available UNLESS you run Python in an embedded environment with stripped down run-time.

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
  • The link says that the first version is BAD because it might hide circular import errors. – Paolo Nov 26 '13 at 20:14
  • Note that while the first version presented here is bad since it might mask something unintended, the original version as used by the asker is not - it prints the actual error that happened. – Aleksi Torhamo Nov 26 '13 at 21:43
  • Please note that on Python 3 one can nest errors when reraising ImportError. This does not apply to Python 2.x though. – Mikko Ohtamaa Nov 26 '13 at 21:48
2

You can doing as the following:

try:
    import sys 
    import os.path
    from logging import handlers
except ImportError as L_err:
    print("ImportError: {0}".format(L_err))
    raise L_err
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
Pipo
  • 4,653
  • 38
  • 47