Более точный способ импортировать модуль из нескольких мест?
Есть ли способ привести в порядок следующий код, а не ряд вложенных операторов 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')
Обратите внимание, я не совсем уверен, красивее ли это, чем подход, использующий вспомогательную функцию.