动态导入模块作为全局变量

Posted

技术标签:

【中文标题】动态导入模块作为全局变量【英文标题】:Dynamically importing modules as global variables 【发布时间】:2021-01-27 01:13:55 【问题描述】:

我正在尝试动态导入模块并将其作为全局变量。

我正在使用 maya 2020 python 解释器(Python 2.7)

我在“/home/arda.kutlu/Downloads/”文件夹下有一个名为“trigger_test_script.py”的测试模块。

当我不导入任何自定义类并运行它时:

###########################################################################[START]
import sys
import imp

class TestClass(object):
    def __init__(self):
        self.filePath = None
        self.asName = None
    
    def action(self):
        exec("global %s" % self.asName, globals())
        foo = "imp.load_source('%s', '/home/arda.kutlu/Downloads/trigger_test_script.py')" %self.asName
        cmd = "0=1".format(self.asName, foo)
        exec(cmd, globals())
###########################################################################[END]
        
test = TestClass()
test.filePath = "/home/arda.kutlu/Downloads/trigger_test_script.py"
test.asName = "supposed_to_be_global"
test.action()
print(supposed_to_be_global)

我得到了我想要的确切结果: <module 'trigger_test_script' from '/home/arda.kutlu/Downloads/trigger_test_script.pyc'>

但是,当我将 TestClass(哈希之间的部分)保存到文件中并像这样导入时:

import testClass
test = testClass.TestClass()
test.filePath = "/home/arda.kutlu/Downloads/trigger_test_script.py"
test.asName = "supposed_to_be_global"
test.action()
print(supposed_to_be_global)

“supposed_to_be_global”的变量没有变成全局变量,我得到了 NameError。

我一直认为这两种用法应该返回相同的结果,但显然我遗漏了一些东西。

感谢任何帮助,谢谢。

【问题讨论】:

exec 发生在运行它的模块的上下文中。您不应该尝试让您的动态加载器动态设置全局变量,尤其是考虑到您必须告诉它要使用的名称。只需...从action 获取模块作为返回值,然后自己分配。 问题是因为globals()返回的值是不同的,当你把TestClass放在一个单独的模块中时——每个模块都有它自己的一组。 我很害怕。这个动作类模块将是几个模块之一,它们都有自己的动作方法,产生不同的结果。所有动作都由另一个控制器类驱动,该控制器类也由 ui 类驱动。我需要一个认真的解决方法来解决这个问题。 【参考方案1】:

我不太明白您关于多个具有不同 action() 方法的模块的最后评论是一个问题。所以忽略这一点,这里是如何使您的问题中的内容起作用,哈希中的部分将在内联或放在单独的模块中并导入时起作用。

###########################################################################[START]
import imp

class TestClass(object):
    def __init__(self):
        self.filePath = None
        self.asName = None

    def action(self):
        foo = imp.load_source(self.asName, self.filePath)
        return foo
###########################################################################[END]

#from testclass import TestClass

test = TestClass()
test.filePath = "/home/arda.kutlu/Downloads/trigger_test_script.py"
test.asName = "supposed_to_be_global"
supposed_to_be_global = test.action()
print(supposed_to_be_global)

【讨论】:

感谢您的回答。通过多种行动方法,我试图说出这样的话。您可能认为这部分是连接到另一个模块的许多动作插件之一。这将是自定义脚本模块,用户可以在其中创建自己的脚本。还有其他模块,如导入几何、构建运动学、替换控制器形状等。可能有任意数量的插件。我的问题是,我也想将导入传递给其他自定义脚本模块,它们都有各自的上下文。用户需要从 ui 中定义 'supposed_to_be_global' 值。 我认为你应该使用字典,而不是全局命名空间来做你想做的事——似乎几乎没有必要用插件的变量来污染它。 谢谢。您能否详细说明在这种情况下如何使用字典? 我的意思是,用户脚本需要通过包含它们的字典来引用事物,而不是它们成为以某种方式存在的全局变量。 是的,我最初的想法是类似的,但这意味着只为这个单个模块改变我的整个结构。我想我无论如何都需要这样做。我知道全局变量就像 exec() 一样不受欢迎,但对于这种情况,我认为我可以利用它。

以上是关于动态导入模块作为全局变量的主要内容,如果未能解决你的问题,请参考以下文章

使用全局变量有可能在导入期间改变模块行为吗?

从导入模块中的函数访问全局变量

专题六.局部变量全局变量global导入模块变量

112.模块导入

112.模块导入

跨模块和全局变量的 Python 导入