2014-02-27 4 views
2

Есть ли способ заставить import x всегда перезагружать x в Python (то есть, как если бы я назвал reload(x) или imp.reload(x) для Python 3)? Или, вообще, есть ли способ заставить некоторый код запускать каждый раз, когда я запускаю import x? Я в порядке с патчем обезьяны или хакером.Python: заставить каждый импорт перезагрузить

Я попытался переместить код в отдельный модуль и удалить x из sys.modules в этом отдельном файле. Я немного потрудился с крючками импорта, но я не слишком старался, потому что, согласно документации, они вызываются только после проверки кеша sys.modules. Я также пробовал monkeypatching sys.modules с пользовательским подклассом dict, но всякий раз, когда я это делаю, from module import submodule поднимает KeyError (я угадываю sys.modules - не настоящий словарь).

В принципе, я пытаюсь написать инструмент отладки (вот почему некоторые хакеры здесь ОК). Моя цель заключается в том, что import x короче, чем import x;x.y.

+2

Если вы действительно хотите изменить семантику оператора 'import', вам придется исправить интерпретатор. 'import' проверяет, загружен ли именованный модуль, и если это так, то он ничего не делает. Вы должны были бы изменить именно это, и это сложно сделать в интерпретаторе. Возможно, вы можете жить с исправлением источников Python, чтобы использовать 'myImport ('modulename')' вместо 'import modulename'? Это сделало бы возможным сам Python. – Alfe

+0

@Alfe: Я думаю, что этот комментарий заслуживает того, чтобы быть отправленным как ответ вместо этого. – jsbueno

+0

Выполнено, и спасибо за поддержку :) – Alfe

ответ

1

Принимая во внимание ответ Альфа, я заставил его работать так. Это происходит на уровне модуля.

def custom_logic(): 
    # Put whatever you want to run when the module is imported here 

# This version is run on the first import 
custom_logic() 

def __myimport__(name, *args, **kwargs): 
    if name == 'x': # Replace with the name of this module 
     # This version is run on all subsequent imports 
     custom_logic() 
    return __origimport__(name, *args, **kwargs) 

# Will only be run on first import 
__builtins__['__origimport__'] = __import__ 
__builtins__['__import__'] = __myimport__ 

Мы monkeypatching __builtins__, поэтому __origimport__ определяется при __myimport__ запуске.

+0

Кажется, что это не работает в PyPy. – asmeurer

3

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

Возможно, вы можете жить с исправлением источников Python для использования myImport('modulename') вместо import modulename? Это сделало бы возможным сам Python.

+0

Хмм, обезглавливание '__import__'. Я об этом не думал. – asmeurer