【问题标题】:Import modules from embedded Python script从嵌入式 Python 脚本导入模块
【发布时间】:2019-05-21 02:43:57
【问题描述】:

tl;dr 如何从嵌入式 Python 脚本中导入 Python 模块,以便导入的模块可以使用宿主系统提供的全局变量和函数?

我正在为某个系统编写 Python 脚本(大概是用 C++ 编写的)。我编写脚本,将其放入一个特殊的预定义文件夹中,系统会在某些事件上执行它。

随着脚本变得庞大而笨拙,我想将其拆分为几个模块,比如说module1.pymodule2.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.

这看起来有点干净,并且没有覆盖某些现有全局变量的风险。由module1module2 导入的模块也可以简单地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.pymain_script.py 然后导入一些模块,但是注入到 main_script.py 中的全局变量不会自动注入到导入的模块中。 “包含所有全局变量的单独文件”从何而来?

标签: python python-embedding


【解决方案1】:

这应该可以解决必须列出两次模块的问题 - 您可以使用 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 文件中,每个模块都从该文件中导入。除此之外,我认为您所拥有的是最简单的方法,如果有其他解决方案我很想听听。

【讨论】:

  • python 的一个好处是,如果 Main 模块导入 A 模块和 B 模块,并且 A 和 B 模块都从 C 模块导入,C 模块将只运行一次。因此,您可以让尽可能多的模块导入相同的核心模块,而无需任何冗余。如果这有任何意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
相关资源
最近更新 更多