"Приобретение знаний - это как путешествие в неизведанные земли: чем больше вы исследуете, тем больше открытий вы делаете".
Библиотека importlib в Python предоставляет инструменты для динамической загрузки модулей. То есть она будет происходить не на этапе анализа кода интерпретатором, а во время выполнения программы. Это полезно, когда некоторые модули не известны до старта программы, например, как при работе с pyspark до инициализации переменных окружения с нужными путями.
Импорт модуля
Самый простой способ динамически загрузить модуль - использовать функцию import_module. Например, встроенный модуль math можно загрузить и использовать так:
Как указывал выше, этот способ спасет при работе с pyspark, вот как импортируются наиболее часто используемые модули:
F = importlib.import_module('pyspark.sql.functions')
T = importlib.import_module('pyspark.sql.types')
Теперь рассмотрим пользовательский модуль следующего содержания:
Для его загрузки понадобится такой код:
Так можно извлечь нужные нам переменные по некоторому правилу:
Часто такое получение переменных применяется при тесте дагов Airflow (подробнее о vars можете прочитать тут):
from airflow import DAG
[k for k,v in vars(func_mod).items() if isinstance(v, DAG)]
Перезагрузка модуля
Если в нашем пользовательском модуле инициализировать дополнительную переменную (c), то потребуется перезагрузка модуля:
Иначе мы не сможем обратиться к переменной:
ни даже после повторной загрузки модуля:
Это происходит из-за кеширования результатов загрузки модуля (подробнее смотри тут). Помочь может очистка специального словаря.
Так, для хранения информации о загруженных модулях используется словарь sys.modules. Когда модуль загружается, его имя добавляется в словарь. Это позволяет системе быстро определить, был ли модуль уже загружен или нет, чтобы избежать повторной загрузки и улучшить производительность.
Словарь sys.modules также может быть использован для управления процессом импорта, например, вы можете удалить оттуда запись о модуле, чтобы система его перезагрузила при очередном импорте:
С функцией reload можно произвести перезагрузку модуля без манипуляций с sys.modules. Добавим еще одну переменную в наш модуль:
Как и ожидалось, сначала она не доступна:
Однако после вызова reload все встает на свои места:
Спецификация модуля
Спецификация модуля предоставляет больше возможностей для работы с модулями в Python и может быть полезна в различных сценариях, например, при изучении параметров модуля и принятия решения о его последующей загрузке.
Для получения объекта ModuleSpec, можно воспользоваться функцией find_spec модуля importlib.util:
Так можно загрузить сам модуль по объекту спецификации:
Следует отметить, что этот способ не добавляет модуль в sys.modules:
Однако ничто не мешает сделать это самим, если надо: