Проверка имени модуля внутри 'except ImportError'

try:
   import MySQLdb
   # some action
except ImportError as err:
   # fallback code

PyCharm дает предупреждение о проверке кода:

'MySQLdb' в блоке try с 'except ImportError' также должен быть определен за исключением блока

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

Хорошо, я думал, что предупреждение разумно, потому что fallback code предполагает, что 'MySQLdb' не установлен, в то время как это может быть некоторая другая ошибка, которая только что подняла ImportError. Поэтому я использовал что-то вроде:

try:
   import MySQLdb
   # some action
except ImportError as err:
   if "MySQLdb" in repr(err):
       # fallback code
   else:
       raise

Предупреждение PyCharm все еще существует, но это может быть просто проблема PyCharm (google показывает проблемы с такими проверками)

Вопросы:

  • Действительно ли стоит проверять имя, когда вы "за исключением ImportError"? Даже в простых случаях (нет some action после import MySQLdb)?

  • Если это стоит проверить, Правильно ли это приведенный выше пример? Если нет - какой правильный путь?

P.S. MySQLdb - это всего лишь пример модуля, который может отсутствовать в системе.

Ответ 1

Я думаю, что вы неправильно поняли предупреждение, если вы не определяете переменную с именем MySQLdb в блоке исключения, а затем, когда вы пытаетесь использовать модуль, вы получите NameError:

try:
    import foo
except ImportError:
    pass

foo.say_foo() #foo may or may not be defined at this point!

Если модуль используется только в предложении try:, это не проблема. Но для более общего случая проверитель ожидает, что вы определите переменную в блоке except:

try:
    import foo
except ImportError:
    foo = None  #now foo always exists

if foo: #if the module is present
    foo.say_foo()
else:
    print("foo") #backup use

Ответ 2

В Python 3.3+ ImportError имеет атрибут name, который сообщает имя модуля, импорт которого не удался. Тогда, конечно, MySQLdb намекнул бы, что вы застряли с Python 2.