【发布时间】:2019-05-21 02:43:57
【问题描述】:
tl;dr 如何从嵌入式 Python 脚本中导入 Python 模块,以便导入的模块可以使用宿主系统提供的全局变量和函数?
我正在为某个系统编写 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
【问题讨论】:
-
您是否尝试将子命名空间引入主命名空间?您可以使用
from module1 import *和from module2 import *。虽然不建议这样做,因为它可能会导致名称冲突。 -
@Sraw,据我所知,我正在尝试做相反的事情。
-
哦,是的。我了解您正在尝试将主命名空间引入子命名空间。听起来确实有点奇怪,因为您似乎对
main_script.py中的“注入的全局变量”没有任何控制权?我假设您应该能够创建一个包含所有全局变量的单独文件,并将该文件导入到主模块和子模块中。 -
@Sraw,一个主机系统(不是用 Python 编写的)加载
main_script.py,注入全局变量并执行main_script.py。main_script.py然后导入一些模块,但是注入到main_script.py中的全局变量不会自动注入到导入的模块中。 “包含所有全局变量的单独文件”从何而来?