来自多个模块的全局变量对exec代码不可见?

时间:2015-10-21 20:33:21

标签: python module exec

我的应用程序通过exec执行存储在配置文件中的python逻辑位,如:

"foo() + 2"

此逻辑通常引用我存储在名为“standard”的模块中的符号。例如,在上面,您可以看到逻辑访问方法foo(),并且foo在standard.py中定义:

def foo():...

为了让逻辑能够访问标准中的符号,我将这些方法从标准中提取到字典中,如下所示:

import standard
my_globals = standard.__dict__

然后我将一些其他相关的符号添加到my_globals(我在这里没有显示)并将它们提供给逻辑,当我执行它时:

exec("foo() + 2", my_globals)

这很有效。当我从foo()内部查看globals()时,我可以看到我在模块standard.py中定义的其他方法以及我上面提到的其他相关符号,foo()可以访问所有这些东西。

当我想要为逻辑提供另一个函数模块时,问题就出现了。假设我有一个名为custom.py的模块,其中包含我希望逻辑访问的其他符号。我试图通过这样做来使这些符号可用:

import custom
my_globals.update(custom.__dict__)

我们现在说我的逻辑是“bar()+ 1”,其中“bar”是在custom.py中定义的。 bar()也想访问我添加到my_globals中的一些相关的其他符号。

我遇到的问题是,custom中的代码只能看到custom.py中定义的符号,而不是my_globals中存储的所有其他符号。 IE,bar()看不到foo(),也看不到我藏在my_globals中的其他东西。

然而foo()可以。它的代码可以看到我在标准中定义的任何其他方法,以及自定义中定义的符号,以及我插入my_globals的“额外”符号。

为什么会这样?我的期望是正在执行的逻辑是在my_globals的内容的上下文中运行的,所以看起来foo()和bar()都应该能够访问my_globals中的任何和所有符号。

我怀疑这与我如何创建my_globals有关。任何见解将不胜感激!

1 个答案:

答案 0 :(得分:1)

以下是一些见解:

  

“为了让逻辑能够访问标准中的符号,我将这些方法从标准中提取到字典中,如下所示:”

import standard
my_globals = standard.__dict__

不完全。您只需创建一个现在指向my_globals的局部变量standard.__dict__。每当您更新my_globals时,您确实只是更新standard.__dict__

当您将其他符号添加到my_globals时,您只需将它们添加到standard.__dict__

通话:

exec("foo() + 2", my_globals)

在standard.py中定义foo时效果很好,因为您已将所有其他方法添加到此模块中 - 您现在可以访问所有这些方法。

当你这样做时:

import custom
my_globals.update(custom.__dict__)

您已将custom.py中的“符号”添加到标准模块中。在此之后,标准中的所有函数都可以从custom.py访问函数

不幸的是,custom.py本身无法直接访问standard.py中的方法(除非您导入它们)。在custom.py中,您可以看到您创建的所有内容现在都是标准的:

(来自custom.py):

import sys

def custom_foo():
    print(dir(sys.modules['standard']))  # shows that you've put everything in here
    sys.modules['standard'].foo()  # calls foo from standard.py (assuming you've imported standard in your main pgm)

上面真的很难看 - 你可以添加一个:

from standard import *

位于custom.py的顶部,您可以访问已添加到__dict__的所有内容。

我怀疑你真的希望用整个exec做你正在尝试的事情,但我不确定你的用例是什么。

修改

如果您确实希望所有附加到my_globals的符号可用于custom.py的方法,则可以调用:

custom.__dict__.update(my_globals)

在此之后,custom.py中的函数可以访问您添加到标准中的所有内容。 dict (又名my_globals)。 (您还使用my_globals中的同名函数覆盖了custom.py中定义的任何函数

请注意,以这种方式做事非常不典型(读:有些不明智)。