从另一个脚本运行脚本时全局名称错误 - python

时间:2013-08-13 18:46:20

标签: python function global

假设我有两个脚本:

test_fun1.py

a = 1

def test1():
    print a
    execfile('test_fun2.py')

test1()

test_fun2.py

b = 2    

def print_a():
    print 'a'

def test2():
    print_a()
    print b

test2()

当我运行test_fun1.py时,我收到此错误:

NameError: global name 'print_a' is not defined

如果我排除print_a() test2() a,则会同时打印b和{{1}}。为什么将变量设置为全局但函数不会?

1 个答案:

答案 0 :(得分:1)

这是一个非常有趣的问题。首先是一个快速的解决方法,您可以在调用execfile()时提供用作本地和全局命名空间的词典,使用globals的空字典可以正常工作:

# test_fun1.py
a = 1

def test1():
    print a
    execfile('test_fun2.py', {})

test1()

或者,如果您希望代码在模块的全局范围内执行,则可以使用globals()代替{}

现在问及为什么这不起作用......来自execfile()的文档:

  

如果省略两个词典,则表达式在调用execfile()的环境中执行。

此处“两个词典”指的是execfile()的可选全局本地参数。在这种情况下,“调用execfile()的环境”是test_fun1.py中函数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 的行为与下面的函数locals()相同:对默认 locals 字典的修改不应该是尝试。如果您需要在函数execfile()返回后查看代码对 locals 的影响,请传递显式的 locals 字典。 execfile()无法可靠地用于修改函数的本地人。

所以你有它,这里有一个明确的警告,execfile()不能用于可靠地修改函数的本地,这正是这段代码试图做的事情。 b = 2def print_a(): ...语句在test1()的范围内执行,但它们实际上并没有成功地将这些名称添加到命名空间,因此稍后尝试访问这些名称失败。