Python 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: (这个不行,在MyClass.main()中出现了“NameError: global name 'time' is not defined”的异常)
def Run():
exec(open("runme.py").read())
print("从函数中运行:")
Run()
caller3.py: (这个可以正常工作,两个 exec()都没有异常)
def Run():
exec(open("runme.py").read())
print("从主作用域运行:") exec(open("runme.py").read())
print("从函数中运行:") Run()
注意,在上面的例子中,'runme.py'的全局命名空间中的time()函数调用总是能成功,而MyClass.main()中的time()函数调用有时能成功,这取决于runme.py是否是在一个函数内部被exec()调用的。
如果我们在函数外部调用exec()(caller1.py),它是有效的。如果我们在函数内部调用exec()(caller2.py),就会失败并抛出异常。如果我们在函数外部调用exec(),然后在函数内部调用(caller3.py),两个 exec()调用都能正常运行,没有异常。
这种行为看起来不太一致。有什么想法吗?我知道这是一个人为的例子,但它是从一个更复杂的程序中提炼出来的,这个程序有一些要求让我们走到了这个地步。
2 个回答
这里有个建议:别用 exec
。基本上,我见过的每次有人用 exec
或 eval
,都是因为他们不知道其实有更好的方法可以实现同样的功能;这就像是一个拐杖,反而妨碍了写出灵活的代码,并不是让代码变得更灵活的办法。
这可能和 'from x import *' 的工作方式有关。如果你在最外层调用这个语句,它会被导入到整个模块的全局变量中。
但是,如果你在一个函数里面调用它,它只会被导入到那个函数的局部变量中。exec() 在 caller2 的函数内部执行,因此 import * 不会进入全局变量,'内层' 的主函数就看不到它。
顺便提一下,如果你尝试这样的代码:
def run():
from time import *
def test():
print time()
test()
run()
你会遇到一个异常:SyntaxError: import * 不允许在函数 'run' 中使用,因为它包含一个有自由变量的嵌套函数。
但这正是你在使用 exec 时所做的,结果却意外地通过了。
不过,考虑到这里的其他回答,为什么不使用其他方法呢?可以看看 'imp' 模块的文档,特别是 find_module 和 load_module 这两个函数。