Модуль importlib

автор

Python предлагает пакет importlib в качестве части стандартной библиотеки модулей. Его задача – обеспечить реализацию оператора импорта Python, а также функции __import__(). В дополнение, importlib дает программисту возможность создать собственный объект (т.н. импортер), который может быть использован для процесса импорта.

Что насчет imp?

Существует еще один модуль, под названием imp, который предоставляет интерфейс механизмам, стоящим за оператором Python import. Этот модуль считается устаревшим для Python 3.4. Предполагается, что importlib следует использовать вместо него.

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

  • Динамический импорт
  • Проверка на возможность импорта модуля
  • Удобный сторонний модуль под названием import_from_github_com

Динамический импорт

Модуль importlib поддерживает возможность импорта модуля, который был передан строке. Так что давайте создадим несколько простых модулей, с которыми мы сможем работать. Мы выделим каждому модулю одинаковый интерфейс, но дадим им выводить свои названия, чтобы увидеть разницу между ними. Создадим два модуля с разными названиями, вроде foo.py и bar.py, и добавим в них следующий код:

Теперь нам остается только использовать importlib чтобы импортировать их. Давайте посмотрим на следующий код, чтобы сделать именно это. Убедитесь в том, что этот код находится в той же папке, что и созданные ранее два модуля.

Здесь мы импортируем модуль importlib и создаем очень простую функцию под названием dynamic_import. Все, что делает эта функция, это вызывает другую функцию importlib — import_module со строкой модуля, который мы ей передали, и возвращает результат этого вызова. Далее, в нашем условном операторе внизу, мы можем вызвать главный метод каждого модуля, который покорно выведет название модуля. Вы, скорее всего, не будете делать это часто в своем коде, но периодически вам может быть нужно импортировать модуль, когда он представлен только в виде строки. Модуль importlib дает возможность сделать именно это.

Проверка импортируемости модуля

Python содержит стиль кодирования под названием EAFP: Easier to ask for forgiveness than permission (легче просить о прощении, чем разрешения). Это значит, что зачастую проще предположить, что что-то существует (к примеру, ключ в словаре), и словить ошибку, если это не так. Ранее мы пытались импортировать модуль, с вероятностью получить ошибку ImportError, если его не существует. Что если нам нужно проверить и увидеть, может ли модуль быть импортированным, чтобы исключить догадки? Вы можете добиться этого с importlib!

Здесь мы импортируем субмодуль из importlib под названием util. В первой части кода check_module содержится настоящая магия, которую мы можем увидеть. В ней мы вызываем функцию find_spec в строке модуля, которая была передана ранее. Сначала мы выполняем передачу фейкового названия, затем мы делаем то же, но с настоящим названием модуля Python. Если вы запустите этот код, вы увидите, что когда вы передаете название неустановленного модуля, функция find_spec вернет None и наш код выведет уведомление о том, что модуль не найден. Если он был найден, тогда мы вернем спецификацию модуля. Мы можем взять эту спецификацию и использовать её для импорта модуля. Или вы можете просто передать строку функции import_module, как мы делали в предыдущем разделе. По этой же причине мы и рассмотрим использование спецификации модуля в качестве альтернативного способа. Взгляните на функцию import_module_from_spec в описанном выше коде. Она принимает спецификацию модуля, которую вернула функция check_module. Далее мы передаем её функции module_from_spec, которая возвращает модуль import. В документации Python рекомендуется запустить модуль после его импорта, это мы и делаем при помощи функции exec_module. Наконец, мы получим модуль и запустим dir Python с ним, чтобы убедиться в том, что данный модуль такой, как мы ожидали.

Импорт из исходного файла

Субмодуль из importlib под названием util может делать один трюк, который я хочу рассмотреть. Вы можете использовать util для импорта модуля, используя только его путь файла и название. Давайте рассмотрим следующий пример, чтобы вы поняли, что к чему:

В данном коде мы импортировали модуль logging и передали его нашей функции import_source. После этого, мы берем настоящие имя и путь модуля. Далее мы вызываем передачу этих частей информации в функцию spec_from_file_location модуля util, которая вернет спецификацию модуля. После этого, мы можем использовать те же механизмы importlib, с которыми мы работали в предыдущем разделе статьи для импорта модуля. Теперь, давайте рассмотрим замечательный сторонний модуль Python, который содержит функцию __import__() для импорта пакетов прямо из github!

Импорт из github.com

Этот удобный в использовании пакет под названием import_from_github_com используется для нахождения и загрузки модулей из github. Для установки, вам нужно использовать pip вот так:

Данный пакет использует несколько инструментов импорта, которые предоставлены в PEP 302, с целью предоставить вам возможность импорта пакета из github. В целом, данный пакет устанавливает другой пакет и добавляет его в локалку. Несмотря на это, вам нужна версия Python начиная с 3.2, а также git и pip для использования данного пакета. После его установки, вы можете попробовать сделать это в вашей оболочке Python:

Выполняется сразу установка модуля из github.

Если вы взглянете на исходный код в import_from_github_com, вы заметите, что он не использует importlib. Вместо этого он использует pip для установки пакета, если он еще не установлен, и затем использует функцию Python __import__(), для непосредственного импорта установленного нового модуля. Это очень креативная часть кода, которой стоит уделить отдельное внимание.

Подведем итоги

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

Вам может быть интересно