这是一个非常有趣的问题。首先是一个快速的解决方法,您可以在调用时提供字典以用作本地和全局命名空间execfile()
,使用空字典可以globals
正常工作:
# test_fun1.py
a = 1
def test1():
print a
execfile('test_fun2.py', {})
test1()
或者,如果您希望代码在模块的全局范围内执行,您可以使用globals()
而不是{}
.
现在谈谈为什么这不起作用......来自以下文档execfile()
:
如果省略了两个字典,则表达式将在execfile()
被调用的环境中执行。
这里的“两个字典”指的是可选的全局变量和局部变量参数execfile()
。在这种情况下,“被调用的环境”是test_fun1.pyexecfile()
中函数的本地范围。test1()
现在仍然期望它能够正常工作是合理的,因为它似乎应该做一些基本上等同于以下内容的事情:
a = 1
def test1():
print a
# code executed by execfile
b = 2
def print_a():
print 'a'
def test2():
print_a()
print b
test2()
test1()
但是稍后在文档中有一条注释:
注意:默认本地人的行为如下所述:不应尝试locals()
修改默认本地人字典。如果您需要在函数返回后查看代码对局部变量的影响,请传递显式局部变量字典。不能可靠地用于修改函数的局部变量。execfile()
execfile()
所以你有了它,这里有一个明确的警告,它execfile()
不能用于可靠地修改函数的局部变量,而这正是这段代码试图做的。b = 2
and语句在的def print_a(): ...
范围内执行test1()
,但它们实际上并没有成功地将这些名称添加到命名空间,因此稍后尝试访问这些名称会失败。