Question

Is there a way to tidy-up the following code, rather than a series of nested try/except statements?

try:
    import simplejson as json
except ImportError:
    try:
        import json
    except ImportError:
        try:
            from django.utils import simplejson as json
        except:
            raise "Requires either simplejson, Python 2.6 or django.utils!"
Was it helpful?

Solution

I found the following function at http://mail.python.org/pipermail/python-list/2007-May/441896.html. It seems to work quite well, and I'm pretty sure the way its importing won't stomp on any existing imports you might already have.

def module_exists(module_name):
    try:
        mod = __import__(module_name)
    except ImportError:
        return False
    else:
        return True

if module_exists('simplejson'):
    import simplejson as json
elif module_exists('json'):
    import json
elif module_exists('django.utils'):
    from django.utils import simplejson as json
else:
    raise ImportError('Requires either simplejson, Python 2.6 or django.utils')

I know this seems like more code, but the function is reusable elsewhere if you're doing a lot of this.

OTHER TIPS

def import_any(*mod_list):
    res = None
    for mod in mod_list:
        try:
            res = __import__(mod)
            return res
        except ImportError:
            pass
    raise ImportError("Requires one of " + ', '.join(mod_list))

json = import_any('simplejson', 'json', 'django.utils.simplejson')

I appreciate the pretty functions for doing this, but the pattern you illustrate in the original question is the most commonly used pattern for this requirement. You can see it used in many open source projects.

I suggest you stick with it. Remember "ugly" is not always "bad".

This avoids the nesting, but I'm not sure it is any better :)

json = None

if json is None:
    try:
        import json
    except ImportError:
        pass

if json is None:
    try:
        import simplejson as json
    except ImportError:
        pass

if json is None:
    try:
        from django.utils import simplejson as json
    except ImportError:
        pass    

if json is None:
    raise ImportError('Requires either simplejson, Python 2.6 or django.utils')

I've come up with a simple alternative that doesn't rely on defining functions:

# Create a dummy enclosing
while True:
    try:
        import simplejson as json
        break
    except:
        pass

    try:
        import json
        break
    except:
        pass

    try:
        from django.utils import simplejson as json
        break
    except:
        pass

    raise ImportError('Requires either simplejson, Python 2.6 or django.utils')

Note, I'm not entirely sure whether it's prettier than the approach using the helper function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top