为什么使用 exec() 时会收到“NameError:名称未定义”?

2023-12-24

当我在控制台(在 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 脚本运行,效果很好(尽管没有可见的结果)。

我认为你实际上可能在做的是这样的:

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 https://docs.python.org/3/library/functions.html#exec),

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

由于上面的代码导入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进入全局范围,一切都可以看到它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么使用 exec() 时会收到“NameError:名称未定义”? 的相关文章

随机推荐