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
答案 0 :(得分:0)
这应该解决必须列出两次模块的问题-您可以使用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文件中。除此之外,我认为您拥有的是最简单的方法,如果还有其他解决方案,我很想听听他们。