Недавно я наткнулся на некоторый код, который использует уловку, которая заставляет меня нервничать.Система, на которую я смотрю, имеет расширение 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 ничего, что указывало бы на то, что это обязательное поведение, а не просто случайность реализации.
Насколько это безопасно?Какими еще способами можно попытаться добиться подобного эффекта «начальной загрузки»?