Importing Python libraries and gracefully handling if they are not availalble
Asked Answered
B

3

9

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()
Bonaventure answered 26/11, 2013 at 19:35 Comment(5)
Your exception handler will fail entirely if importing sys fails.Tyrannize
I'd leave out the standard libraries here. Why would importing those fail at all?Tyrannize
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?Tyrannize
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.Cumbrous
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.Krouse
A
14

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
Audreaaudres answered 26/11, 2013 at 21:27 Comment(1)
I like this solution better because it uses basic python without the need of importing extra libraries.Bonaventure
K
7

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.

Krouse answered 26/11, 2013 at 20:7 Comment(3)
The link says that the first version is BAD because it might hide circular import errors.Alike
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.Audreaaudres
Please note that on Python 3 one can nest errors when reraising ImportError. This does not apply to Python 2.x though.Krouse
E
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
Empiricism answered 9/11, 2018 at 13:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.