Python 为什么我会得到;名称错误:未定义名称";使用exec()?

Python 为什么我会得到;名称错误:未定义名称";使用exec()?,python,python-3.x,scope,python-import,python-exec,Python,Python 3.x,Scope,Python Import,Python Exec,当我在控制台(PyCharm)中尝试此代码时: 它很好用。但是,当我试图在我的程序中执行完全相同的操作时,它不起作用,我得到了一个例外 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(),

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

它很好用。但是,当我试图在我的程序中执行完全相同的操作时,它不起作用,我得到了一个例外

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()
上述代码确实会导致您问题中提到的
namererror
异常,因为(引用

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

由于上面的代码将
随机
导入到
import\u stuff()
的本地范围,因此
do\u 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
导入全局范围,所有人都可以看到它

def import_stuff():
    import random

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

do_stuff()