【问题标题】:Why do I get "NameError: name is not defined" with exec()?为什么我用 exec() 得到“NameError: name is not defined”?
【发布时间】:2019-02-23 09:42:15
【问题描述】:

当我在控制台(在 PyCharm 中)尝试此代码时:

exec("import random")
exec("def f():\n\treturn random.randint(0, 10), random.randint(0, 10)")
locals()['f']()

它工作正常。但是当我尝试在我的程序中做同样的事情时它不起作用,我得到了异常

NameError: name 'random' is not defined.

我发现这段代码不会引发错误:

exec("import random", globals(), globals())
exec("def f():\n\treturn random.randint(0, 10), random.randint(0, 10)", globals(), globals())
globals()['f']()

但我不明白为什么。

发生了什么事?

【问题讨论】:

    标签: python python-3.x scope python-import python-exec


    【解决方案1】:

    你在你的程序中做的不是“完全相同”。将确切的代码逐字复制到文件中并作为 Python 脚本运行,运行良好(尽管没有可见的结果)。

    我认为您实际上可能正在做的是这样的事情:

    def import_stuff():
        exec("import random")
    
    def do_stuff():
        import_stuff()
        exec("def f():\n\treturn random.randint(0, 10), random.randint(0, 10)")
        locals()['f']()
    
    do_stuff()
    

    上面的代码确实会导致您的问题中提到的NameError 异常,因为(引用docs),

    在所有情况下,如果省略可选部分,则代码在当前范围内执行。

    由于上面的代码将random 导入到import_stuff() 的本地范围内,因此do_stuff() 看不到它。

    实际上,上面的代码在行为上与以下代码相同:

    def import_stuff():
        import random
    
    def do_stuff():
        import_stuff()
        def f():
            return random.randint(0, 10), random.randint(0, 10)
        f()
    
    do_stuff()
    

    ...同样的原因也失败了。

    假设这是您的实际代码中实际发生的情况,通过将globals(), globals() 参数添加到exec() 来修改您的问题的版本将起作用,因为您将random 显式导入全局范围,一切都可以看到。

    【讨论】:

      猜你喜欢
      • 2020-04-08
      • 1970-01-01
      • 2012-06-13
      • 2017-04-13
      • 1970-01-01
      • 2015-01-20
      • 2021-09-08
      • 1970-01-01
      • 2019-02-18
      相关资源
      最近更新 更多