【问题标题】:error with global name when running a script from another script - python从另一个脚本运行脚本时全局名称出错 - python
【发布时间】:2013-08-13 18:46:19
【问题描述】:

假设我有两个脚本:

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

如果我在test2() 中排除print_a()ab 都会被打印出来。为什么变量会设置为全局而函数不会?

【问题讨论】:

  • 你的意思是 a 和 b 都是从 test_fun2.py 打印的? (或者它可能来自test1())?另外,您是否考虑过只导入外部脚本?
  • 也许这对你有帮助? stackoverflow.com/questions/2904274/…
  • @sihrc:当 print_a() 从代码中排除时,a 从 test1() 打印,b 从 test2() 打印。
  • 那么,变量就不是“全局的”了。
  • @sihrc:我的意思是我可以在函数内部使用 a 和 b,尽管它们是在函数外部定义的。不过,我还没有使用“global”命令将它们声明为全局。

标签: python function global


【解决方案1】:

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

# test_fun1.py
a = 1

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

test1()

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

现在了解为什么这不起作用...从execfile() 上的文档:

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

这里的“两个字典”是指execfile() 的可选globalslocals 参数。在这种情况下,“调用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() 的范围内执行,但它们实际上并未成功地将这些名称添加到命名空间,因此稍后尝试访问这些名称会失败。

【讨论】:

  • 感谢您的回答。我实际上可以在 test2() 中使用 b - 当 print_a() 语句从 test2() 中删除时,a 和 b 都会被打印,所以我仍然可以访问 b。那么您的解释是否仅适用于函数?
  • 不幸的是,当文档说“execfile() 不能可靠地用于修改函数的局部变量”时,文档有点模糊。很可能变量赋值和函数定义之间存在差异,但我真的不知道,我也不打算深入研究 Python 源代码来找出答案。这里的要点是,您确实应该为execfile() 提供一个 globals 参数,否则行为将根据调用发生的位置而不一致。
猜你喜欢
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多