为啥执行 exec('print(x)') 而 print(x) 在此 python 代码中出错?

Posted

技术标签:

【中文标题】为啥执行 exec(\'print(x)\') 而 print(x) 在此 python 代码中出错?【英文标题】:why exec('print(x)') is executed while print(x) goes wrong in this python code?为什么执行 exec('print(x)') 而 print(x) 在此 python 代码中出错? 【发布时间】:2021-04-02 02:51:12 【问题描述】:
def build(s, loc):
    exec(s, loc)
    return loc

def main():
    L = build('x = 1', locals())
    locals().update(L)
    exec('print(x)')

  
if __name__ == '__main__':  
    main()

当我运行上面的代码时,python 控制台会显示 '1'。

def build(s, loc):
    exec(s, loc)
    return loc

def main():
    L = build('x = 1', locals())
    locals().update(L)
    print(x)
  

if __name__ == '__main__':  
    main()

当我运行上面的代码时,它会显示'name 'x' is not defined'。

它们有什么区别?

我修改了代码以减少歧义,但仍然存在类似问题。

def main():
    exec('x = 1')
    exec('print(x)')
    
  
if __name__ == '__main__':  
    main()

这将显示“1”。

def main():
    exec('x = 1')
    print(x)
    
  
if __name__ == '__main__':  
    main()

这会出错。

【问题讨论】:

修改locals 是未定义的行为。 感谢您的回答。我添加更多细节,类似的错误仍然存​​在。 exec修改局部变量也是未定义的行为。 我假设它可能是解释器不理解exec('x = 1') 实例化了一个新变量x,因此错误地假设您的第二个代码在执行前校对它时包含语法错误 - 而它应该可以正常运行,因此当通过 exec 调用调用 x 时,在您的第一个示例中通过语法检查就好了 【参考方案1】:

这与范围有关。

当这样做时:

def main():
    exec('x = 1')
    print(x)


if __name__ == '__main__':  
    main()

exec 定义的 x 变量是局部的,与传递给 print() 函数的 x 变量不同,后者是全局的。除非你告诉它:

def main():
    exec('global x;x = 1')
    print(x)
    
  
if __name__ == '__main__':  
    main()

这最终对我有用,它打印 1。

这是因为在 exec() 中对 x 变量使用 global 关键字后,您告诉解释器尽管在本地范围内,对 x 变量的任何进一步引用都将引用外部,全局,x变量。

【讨论】:

感谢您的回答。但是如果我将 main() 函数修改为:def main():x =1;print(locals()['x']);print(x),它会打印 '1/n1'。这意味着 x 仍然是一个局部变量,即使 x 由 x = 1 定义。如果将 main() 修改为: def main():x=1;print(globals()['x'];print(x)) ,就会发生KeyError。

以上是关于为啥执行 exec('print(x)') 而 print(x) 在此 python 代码中出错?的主要内容,如果未能解决你的问题,请参考以下文章

print, repr, str, eval,exec使用

print, repr, str, eval,exec使用

为啥 x -= x + 4 返回 -4 而不是 4

为啥 Runtime.getRuntime().exec(startupOracle);没有完全执行命令

23 24 25 py中break和continue 循环中的else语句 exec和eval函数

PHP:exec()函数为啥没有反应呢?