Импорт модулей из встроенного скрипта Python - PullRequest
0 голосов
/ 21 мая 2019

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

1 Ответ

0 голосов
/ 21 мая 2019

Это должно решить необходимость дважды перечислять модули - вы можете использовать библиотеку importlib для импорта модулей из имен переменных

>>> import importlib
>>> np = importlib.import_module('numpy')
>>> np.pi
3.141592653589793

Так что из списка это будет

import importlib
modules = [importlib.import_module(module_name) for module_name in module_names]
for m in modules:
    ...

Что касается синхронизации глобалов, мне неприятно это говорить, но я думаю, что нет идеального способа сделать это.Я сталкивался с этой проблемой раньше, и мое решение состояло в том, чтобы поместить каждую функцию или переменную, которую я хотел, чтобы они были доступны в каждом модуле, в отдельный файл core.py, из которого импортировался каждый модуль.Кроме того, я думаю, что у вас есть самый простой способ сделать это, если есть другие решения, мне было бы интересно их услышать.

...