tl; dr Как импортировать модуль Python из встроенного скрипта Python, чтобы импортированный модуль мог использовать глобальные переменные и функции, предоставляемые хост-системой?
IЯ пишу сценарий Python для какой-либо системы (написана предположительно на C ++).Я пишу сценарий, помещаю его в специальную предопределенную папку, система выполняет его для некоторых событий.
Поскольку сценарий становится большим и громоздким, я хочу разделить его на несколько модулей, скажем, module1.py
и module2.py
, импортированный main_script.py
, который загружается и выполняется хост-системой.Однако импортированные модули не могут использовать глобальные вещи, которые main_script.py
может (я полагаю, система хоста добавляет некоторые глобальные переменные, функции, классы и т. Д. При загрузке main_script.py
; однако модули не загружаются системой хоста напрямую).таким образом, они не имеют всех этих глобалов).
До сих пор я придумал следующее - он ищет глобалы, присутствующие в main_script.py
, но не в модулях, и добавляетих для модулей:
#main_script.py
import module1, module2
for m in [module1, module2]:
for k, v in globals().items():
if not hasattr(m, k):
setattr(m, k, v)
Это работает (по крайней мере, в моем случае до сих пор), но не выглядит особенно элегантно: мне нужно дважды перечислить импортированные модули;если я хочу импортировать некоторые подмодули из модулей, я должен был бы сделать то же самое там;Я должен остерегаться возможных глобальных столкновений имен и т. Д.) Поскольку проблема звучит не так уж редко, я чувствую, что, возможно, я изобретаю здесь квадратное колесо.Есть ли лучший способ сделать это?
UPD.: На основе [моей интерпретации?] Предложений из ответа @Merlin Katz и комментария от @Sraw, яизменил мои скрипты следующим образом.Сначала добавлен пустой скрипт core.py
.Затем измените main_script.py
:
#main_script.py
import core
#only inject into the empty 'core' module
for k, v in globals().items():
if not hasattr(core, k):
setattr(core, k, v)
#can now import modules that depend on those globals
import module1, module2
Затем каждый модуль, который должен использовать введенные глобалы, должен импортировать core
и использовать их оттуда:
#module1.py
import core
_blah = core.blahblah #a shortcut
core.call_global_function()
my_obj1 = core.blahblah.SomeClassDefinedInBlahblah()
my_obj2 = _blah.SomeClassDefinedInBlahblah() #a bit shorter version of the above
#etc.
Это выглядит несколько чищеи нет риска перезаписать некоторые существующие глобальные переменные.Модули, импортированные module1
и module2
, также могут просто import core
и использовать глобальные переменные.
UPD.: Кроме того, я не уверен, стоит ли это того,но вместо того, чтобы хранить пустой модуль core.py
, вы можете создать его динамически:
#main_script.py
import sys
from types import ModuleType
core = ModuleType("core")
sys.modules["core"] = core
#inject into our dynamically created 'core' module
for k, v in globals().items():
if not hasattr(core, k):
setattr(core, k, v)
#the modules can still import `core` the same way as before
import module1, module2