Модули Python, заменяющие себя во время загрузки - PullRequest
1 голос
/ 18 апреля 2019

Недавно я наткнулся на некоторый код, который использует уловку, которая заставляет меня нервничать.Система, на которую я смотрю, имеет расширение Moo.so с расширением Python, которое хранится вне пути, и разработчик хочет импортировать его с помощью import Moo.По разным причинам ни местоположение файла, ни sys.path не могут быть изменены, и расширение должно быть загружено с помощью ExtensionFileLoader в любом случае.

Итак, что было сделано, это иметь Moo.py в пути, который загружаетмодуль расширения, а затем заменяет себя в sys.modules модулем расширения следующим образом:

' Moo.py '

from importlib.machinery import ExtensionFileLoader

loader = ExtensionFileLoader('AnotherNameForMoo', '/path/to/Moo.so')
module = loader.load_module()
sys.modules['Moo'] = module

Теперь это действительно работает.(У меня есть несколько тестов этого довольно подробно в этом репо , если вы хотите посмотреть.) Похоже, что, по крайней мере, в CPython 3.4 до 3.7, import Moo не связывается с Moo модуль, который был загружен и помещен в sys.modules['Moo'], но вместо этого связывает текущее значение из sys.modules['Moo'] после того, как скрипт верхнего уровня модуля возвращается, независимо от того, был ли он изначально туда вставлен.

Я не могу найти в документации Python ничего, что указывало бы на то, что это обязательное поведение, а не просто случайность реализации.

Насколько это безопасно?Какими еще способами можно попытаться добиться подобного эффекта «начальной загрузки»?

...