Python exec()的行为取决于它的调用位置

时间:2010-08-26 19:05:27

标签: python scope exec

我有一个Python脚本'runme.py',我试图从下面的'callerX.py'执行。我正在使用exec(open(filename).read())来完成此任务。正在执行的脚本包含一个简单的类,它试图从全局命名空间和“全局命名空间”调用'time()'函数。在一个函数内部。

在下面的所有示例中,我们使用exec()执行以下文件:


# runme.py
# this code is being exec()'d by the stand-alone examples 1-3 below:
from time import *

class MyClass():
    def main(self):
        print("Local tracepoint 1")
        t = time()
        print("Local tracepoint 2")

mc = MyClass()
print("Tracepoint 1")
gt = time()
print("Tracepoint 2")
mc.main()
print("Tracepoint 3")


caller1.py :(这个工作正常,'time'函数可以在MyClass.main()中使用)


print("Run from main scope:")
exec(open("runme.py").read())

caller2.py :(这不起作用,失败,出现异常“NameError:未定义全局名称'时间'”MyClass.main()内部

def Run():
    exec(open("runme.py").read())

print("Run from function:") Run()


caller3.py :(这个工作正常,两个 exec()运行没有例外)

def Run():
    exec(open("runme.py").read())

print("Run from main scope:") exec(open("runme.py").read())

print("Run from function:") Run()

请注意,在上面的示例中,对'runme.py'的全局命名空间中的time()函数的调用始终有效,并且从MyClass.main()调用time()函数有时只能工作,取决于文件runme.py是否来自函数内的exec()。

如果我们从函数(caller1.py)外部调用exec(),它就可以工作。如果我们从函数(caller2.py)中调用exec(),它将失败并显示异常。如果我们从函数外部调用exec(),然后从函数内部调用(caller3.py),那么两个调用exec()都会运行而没有异常。

此行为似乎不一致。有任何想法吗?我知道这是一个人为的例子,然而,它是从一个更复杂的程序中提炼出来的,这个程序的要求已经把我们带到了这个关键时刻。

2 个答案:

答案 0 :(得分:0)

这可能与'from x import *'的工作原理有关。如果你从'top-level'调用它,它将导入整个模块的globals()。

但是,如果在函数内部调用它,它只会导入到函数中的locals()中。 exec()在caller2中的函数内得到评估;因此,import *不会进入globals(),而'inner'主函数看不到它。

顺便说一句:如果您尝试这样的代码,那就很有趣了:

def run():
    from time import *
    def test():
        print time()
    test()
run()

你会得到一个异常:SyntaxError:import *在函数'run'中是不允许的,因为它包含一个带有自由变量的嵌套函数

但这正是你对执行官的所作所为,但它却以某种方式令人惊讶地偷偷摸摸。

但是 - 考虑到其他答案 - 为什么不使用其他东西呢?查看'imp'模块文档 - 特别是函数find_module和load_module。

答案 1 :(得分:-1)

这是一个想法:不要使用exec。基本上每当我看到有人使用execeval时,都会因为他们不知道已经存在更好的方法来完成相同的事情。它是一个阻碍编写动态代码的拐杖,而不是编写某种动态代码的方法。