Более точный способ импортировать модуль из нескольких мест?

Есть ли способ привести в порядок следующий код, а не ряд вложенных операторов try/исключением?

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!"

Ответ 1

Я нашел следующую функцию в http://mail.python.org/pipermail/python-list/2007-May/441896.html. Кажется, он работает довольно хорошо, и я уверен, что его импорт не помешает любому существующему импорту, который у вас уже есть.

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')

Я знаю, что это похоже на дополнительный код, но эту функцию можно использовать в другом месте, если вы делаете это много.

Ответ 2

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')

Ответ 3

Я ценю красивые функции для этого, но шаблон, который вы иллюстрируете в исходном вопросе, является наиболее часто используемым шаблоном для этого требования. Вы можете видеть, что это используется во многих проектах с открытым исходным кодом.

Я предлагаю вам придерживаться этого. Помните, что "некрасиво" не всегда "плохо".

Ответ 4

Это позволяет избежать вложенности, но я не уверен, что она лучше :)

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')

Ответ 5

Я предложил простую альтернативу, которая не зависит от определения функций:

# 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')

Обратите внимание, я не совсем уверен, красивее ли это, чем подход, использующий вспомогательную функцию.