Подтвердить что ты не робот

Как переопределить импорт Python?

Я работаю над pypreprocessor, который является препроцессором, который принимает директивы c-style, и я смог сделать это работать как традиционный препроцессор (он самозатягивается и выполняет постпроцессированный код "на лету" ), за исключением того, что он прерывает импорт библиотеки.

Проблема заключается в следующем: препроцессор запускает файл, обрабатывает его, выдает во временный файл и exec() временный файл. Библиотеки, которые импортируются, нужно обрабатывать немного иначе, потому что они не выполняются, а скорее загружаются и становятся доступными для модуля вызывающего абонента.

Что мне нужно сделать, это: Прервать импорт (поскольку препроцессор выполняется в середине импорта), загружать постобрабованный код в качестве tempModule и заменять исходный импорт tempModule, чтобы обмануть вызывая script с импортом, полагая, что tempModule является исходным модулем.

Я искал везде и до сих пор и не имею решения.

Этот вопрос о переполнении стека является самым близким, который я видел до сих пор, чтобы дать ответ: Переопределить пространство имен в Python

Вот что у меня есть.

# Remove the bytecode file created by the first import
os.remove(moduleName + '.pyc')

# Remove the first import
del sys.modules[moduleName]

# Import the postprocessed module
tmpModule = __import__(tmpModuleName)

# Set first module reference to point to the preprocessed module
sys.modules[moduleName] = tmpModule

moduleName - это имя исходного модуля, а tmpModuleName - это имя файла постпроцессированного кода.

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

Надеюсь, что кто-то из Qaru знает намного больше об импорте, чем я, потому что этот имеет меня в тупике.

Примечание. Я буду награждать только решение или, если это невозможно в Python; лучшее, самое подробное объяснение, почему это не невозможно.

Обновление: для любого, кто заинтересован, вот рабочий код.

if imp.lock_held() is True:
    del sys.modules[moduleName]
    sys.modules[tmpModuleName] = __import__(tmpModuleName)
    sys.modules[moduleName] = __import__(tmpModuleName)

Часть "imp.lock_held" определяет, загружается ли модуль в виде библиотеки. Следующие строки делают все остальное.

4b9b3361

Ответ 1

Отвечает ли это на ваш вопрос? Второй импорт делает трюк.

Mod_1.py

def test_function():
    print "Test Function -- Mod 1"

Mod_2.py

def test_function():
    print "Test Function -- Mod 2"

Test.py

#!/usr/bin/python

import sys

import Mod_1

Mod_1.test_function()

del sys.modules['Mod_1']

sys.modules['Mod_1'] = __import__('Mod_2')

import Mod_1

Mod_1.test_function()

Ответ 2

Чтобы определить другое поведение импорта или полностью подорвать процесс импорта, вам нужно будет написать импортные крючки. См. PEP 302.

Например,

import sys

class MyImporter(object):

    def find_module(self, module_name, package_path):
        # Return a loader
        return self

    def load_module(self, module_name):
        # Return a module
        return self

sys.meta_path.append(MyImporter())

import now_you_can_import_any_name
print now_you_can_import_any_name

Он выводит:

<__main__.MyImporter object at 0x009F85F0>

Таким образом, в основном он возвращает новый модуль (который может быть любым объектом), в этом случае сам. Вы можете использовать его для изменения поведения импорта, возвращая processe_xxx при импорте xxx.

IMO: Python не нуждается в препроцессоре. Независимо от того, что вы делаете, это может быть выполнено в самом Python из-за его очень динамичного характера, например, принимая пример отладки, что не так с наличием в верхней части файла

debug = 1

и позже

if debug:
   print "wow"

?

Ответ 3

В Python 2 есть модуль imputil, который, как представляется, обеспечивает функциональность, которую вы ищете, но был удален в python 3. Он не очень хорошо документирован, но содержит примерный раздел, в котором показано, как вы можете заменить стандартные функции импорта.

Для Python 3 существует модуль importlib (представленный в Python 3.1), который содержит функции и классы для изменения функций импорта в всевозможные способы. Он должен быть подходящим для подключения вашего препроцессора к системе импорта.

Ответ 4

Очень странный подход - эмулировать язык низкого уровня с высокоуровневым. Если первый простой способ не работает, может быть, это неправильная цель?

BTW, препроцессор C просто работает с текстовыми файлами и набором препроцессорных переменных, а не с загруженными/невыгруженными модулями высокого уровня.