Why do I get "NameError: name is not defined" with exec()?
Why do I get "NameError: name is not defined" with exec()?
当我在控制台(在 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),
In all cases, if the optional parts are omitted, the code is executed in the current scope.
由于上面的代码将 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()
... 也失败了,原因相同。
假设这就是您的真实代码中实际发生的事情,那么通过向 exec()
添加 globals(), globals()
参数来修改您的问题的版本会起作用,因为这样您就明确地导入了 random
进入全局范围,一切都可以看到它。
当我在控制台(在 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),
In all cases, if the optional parts are omitted, the code is executed in the current scope.
由于上面的代码将 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()
... 也失败了,原因相同。
假设这就是您的真实代码中实际发生的事情,那么通过向 exec()
添加 globals(), globals()
参数来修改您的问题的版本会起作用,因为这样您就明确地导入了 random
进入全局范围,一切都可以看到它。