为什么在函数内部调用exec()时会产生不同的工作,以及如何避免使用

时间:2019-04-19 14:10:32

标签: python python-2.7 exec

我正在尝试在python的 exec 语句中声明两个函数。我们称它们为 f1() f2()

我发现,当在某个函数中调用 exec 时, f2() f1()没有可见性。 但是,将 exec 和函数调用放在全局代码中不会发生这种情况。

# Case 1: Working fine

code = """
def f1(): print "bar"
def f2(): f1()
"""

exec(code)
f2() # Prints "bar" as expected
# Case 2: Throws NameError: global name 'f1' is not defined

code = """
def f1(): print "bar"
def f2(): f1()
"""

def foo():
    exec(code)
    f2() # NameError

foo()

有人可以向我解释如何避免NameError并使 exec 在函数内部工作吗?

3 个答案:

答案 0 :(得分:5)

exec()接受globals的第二个参数。如docs中所述:

  

注意:内置函数globals()和locals()分别返回当前的全局字典和局部字典,这对于传递给exec()的第二个和第三个参数可能很有用。

因此,您可以通过显式传递globals()来完成这项工作:

code = """
def f1(): print ("bar")
def f2(): f1()
"""

def foo():
    exec(code, globals())
    f2() # works in python2.7 and python3

foo()

如果要精确控制范围,可以将对象传递到exec

code = """
def f1(): print ("bar")
def f2(): f1()
"""

def foo():
    context = {}
    exec(code, context)
    context['f2']() 

foo() 

答案 1 :(得分:2)

Kevin的评论很好,并且需要重复一遍-使用exec很危险,几乎总是有更好的方法。

但是,在第一种情况下,针对您的问题,f1()和f2()都位于全局命名空间中,因此当您调用f2()时,它可以找到f1()。在第二种情况下,它们是在foo()函数的本地空间中创建的。调用f2()时,找不到本地f1()定义。

您可以使用以下方法解决此问题:

code = """
global f1
def f1(): print "bar"
def f2(): f1()
"""
def foo():
    exec(code)
    f2()
foo()

再次-这几乎肯定不是您要解决此问题的方法。

**编辑**发布了我一直在检查的错误版本的代码,这个版本是我本应包含的。

答案 2 :(得分:-1)

“在所有情况下,如果省略[exec()的可选部分),则代码将在当前作用域中执行。”

https://docs.python.org/3.5/library/functions.html#exec