Полноценная поддержка того, что вы просите, вероятно, требует сложного кода с использованием importlib
и подключения к различным частям импортного оборудования. Однако более ограниченное решение может быть реализовано только с одним пользовательским классом, который претендует на роль модуля.
При импорте модуля Python сначала проверяет в словаре sys.modules
, чтобы узнать, является ли модуль ключом. Если это так, он возвращает значение, связанное с ключом. Он делает это независимо от значения, поэтому вы можете поместить любой объект в sys.modules
, и Python будет рассматривать его как модуль. Код модуля может даже заменить его собственную запись в sys.modules
, и замена будет использоваться даже в первый раз, когда это import
ed!
Итак, чтобы реализовать свой модный модуль, который загружает другие модули по требованию, замените сам модуль экземпляром пользовательского класса и напишите этот класс __getattr__
или __getattribute__
, который выполняет нужную работу.
Вот тривиальный примерный модуль, который возвращает строку для любого атрибута, который вы ищете в нем. Строка всегда будет такой же, как имя запрашиваемого атрибута. В вашем коде вы хотели бы выполнять ваши фантастические поиски и загрузку веб-кешей, а затем возвращать извлеченный объект модуля вместо того, чтобы просто возвращать строку.
class FakeModule(object):
def __getattribute__(self, name):
return name
import sys
sys.modules[__name__] = FakeModule()
В моей системе я сохранил, что, как fakemodule.py
. Теперь, если я делаю from fakemodule import foo
, я получаю foo
со значением 'foo'
в своем локальном пространстве имен.
Обратите внимание, что это работает только для одного уровня глубокого импорта. Если вы делаете from fakemodule.subpackage import name
, это не сработает, потому что нет fakemodule.subpackage
записей в sys.modules
.
Я уверен, что есть способы сделать это, но я бы попросил, чтобы вы этого не сделали. Идем дальше и открываем терминал python и запускаем 'import this'. Что говорит вторая строка? «Явный лучше, чем неявный». Это очень важно для написания хорошего Python. Имея модуль, который делает всевозможные странные вещи на заднем плане, не обращаясь к программисту, это не очень Pythonic. – IanAuld
Хорошо. Лучше ли тогда написать функцию «cloud.Import (« test_module »)», чтобы заменить встроенный импорт? –
Дизайн, который вы здесь описываете, - декоратор.Импорт запускается в импортированном модуле, но вы всегда получаете ту же самую функциональность. –