2016-02-21 5 views
0

Я строю модуль Python для определенной цели. То, что я хотел бы сделать с этим, - получить больше функциональных возможностей за счет import.Захват оператора импорта python

Я хотел бы иметь установку, с помощью которой from my_module import foo будет запускать функцию и передать строку "foo". Эта функция вернет объект, который должен быть импортирован.

Например, возможно, я хочу создать облачную систему импорта. Я хотел бы сохранить сценарии сообщества в облаке, а затем загрузить их, когда пользователь попытается их импортировать.

Возможно, я использую код from cloud import test_module. Это проверит кеш, чтобы решить, был ли загружен test_module. Если это так, он вернет этот модуль. Если нет, он загрузит модуль перед импортом.

Как я могу выполнить что-то подобное в Python, с помощью которого динамический диапазон подмодулей может быть плавным import ed из облака?

+0

Я уверен, что есть способы сделать это, но я бы попросил, чтобы вы этого не сделали. Идем дальше и открываем терминал python и запускаем 'import this'. Что говорит вторая строка? «Явный лучше, чем неявный». Это очень важно для написания хорошего Python. Имея модуль, который делает всевозможные странные вещи на заднем плане, не обращаясь к программисту, это не очень Pythonic. – IanAuld

+0

Хорошо. Лучше ли тогда написать функцию «cloud.Import (« test_module »)», чтобы заменить встроенный импорт? –

+0

Дизайн, который вы здесь описываете, - декоратор.Импорт запускается в импортированном модуле, но вы всегда получаете ту же самую функциональность. –

ответ

1

Полноценная поддержка того, что вы просите, вероятно, требует сложного кода с использованием 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.

+0

Это потрясающе, я понятия не имел, что могу это сделать. Это именно то, что мне нужно, спасибо. –