Надеюсь, следующий вопрос не слишком длинный. Но в противном случае я не могу объяснить проблему и то, что хочу:Как использовать sys.path_hooks для индивидуальной загрузки модулей?
Ученый от How to use importlib to import modules from arbitrary sources? (мой вопрос вчера) Я написал specfic-загрузчик для нового типа файла (.xxx). (На самом деле xxx - это зашифрованная версия pyc для защиты кода от кражи).
Я хотел бы только добавить крюк импорта для нового типа файла "xxx", не затрагивая другие типы (.py, .pyc, .pyd) любым способом.
Теперь грузчик ModuleLoader
, наследующий от mportlib.machinery.SourcelessFileLoader
.
Использование sys.path_hooks
загрузчик должен быть добавлен в качестве крючка:
myFinder = importlib.machinery.FileFinder
loader_details = (ModuleLoader, ['.xxx'])
sys.path_hooks.append(myFinder.path_hook(loader_details))
Примечание: Это срабатывает один раз по телефону modloader.activateLoader()
При загрузке модуль с именем test
(который является test.xxx
) я получаю:
>>> import modloader
>>> modloader.activateLoader()
>>> import test
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'test'
>>>
Однако, когда я удалить содержимое sys.path_hooks
перед добавлением крюк:
sys.path_hooks = []
sys.path.insert(0, '.') # current directory
sys.path_hooks.append(myFinder.path_hook(loader_details))
это работает:
>>> modloader.activateLoader()
>>> import test
using xxx class
in xxxLoader exec_module
in xxxLoader get_code: .\test.xxx
ANALYZING ...
GENERATE CODE OBJECT ...
2 0 LOAD_CONST 0
3 LOAD_CONST 1 ('foo2')
6 MAKE_FUNCTION 0
9 STORE_NAME 0 (foo2)
12 LOAD_CONST 2 (None)
15 RETURN_VALUE
>>>>>> test
<module 'test' from '.\\test.xxx'>
модуль импортируется корректно после преобразования содержимого файлов в объект кода.
Однако я не могу загрузить один и тот же модуль из пакета:import pack.test
Примечание: __init__.py
, конечно, как пустой файл в директории пакета.
>>> import pack.test
Traceback (most recent call last):
File "<frozen importlib._bootstrap>", line 2218, in _find_and_load_unlocked
AttributeError: 'module' object has no attribute '__path__'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'pack.test'; 'pack' is not a package
>>>
не хватает, я не могу загрузить простые * .py модулей из этого пакета больше: я получаю ту же ошибку, что и выше:
>>> import pack.testpy
Traceback (most recent call last):
File "<frozen importlib._bootstrap>", line 2218, in _find_and_load_unlocked
AttributeError: 'module' object has no attribute '__path__'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'pack.testpy'; 'pack' is not a package
>>>
Для моего понимания sys.path_hooks
проходятся, пока последняя запись не пробовала , Итак, почему первый вариант (без удаления sys.path_hooks
) не распознает новое расширение «xxx», а второй вариант (удаление sys.path_hooks
)? Похоже, что механизм генерирует исключение, а не переходит к следующей записи, когда запись sys.path_hooks
не может распознать «xxx».
И почему вторая версия работает для ру, ВПГ и ххх модулей в текущем каталоге, но не работает в пакете pack
? Я бы ожидал, что py и pyc даже не работают в текущем каталоге, потому что sys.path_hooks
содержит только крючок для «xxx» ...
Не использовать python 3, так что не могу помочь здесь - как бы резюмировать ваши вопросы, это помогло бы другому ответу. Может быть, попробуйте 'sys.path_hooks.insert (0, myFinder.path_hook (loader_details))'? Вопросы остаются –