所以我有一个像
这样的函数的字符串code = """def somefn(x):
return x + x
y = somefn(z)"""
我试图在另一个函数中运行它,比如
def otherfn(codestr):
z = 2
exec(codestr)
return y
otherfn(code)
但它给了我错误:
追踪(最近一次通话): 文件“C:/Users/Admin/Desktop/heh.py”,第11行,in otherfn(代码) 文件“C:/Users/Admin/Desktop/heh.py”,第9行,in otherfn 回来 NameError:名称'y'未定义
它在
之类的功能之外正常工作 z=2
exec(codestr)
print(y)
它发现你很好但不确定为什么它在函数中时会出现问题。
我该如何解决这个问题?它与globals()和locals()有关吗?使用Python 3.6 btw。
答案 0 :(得分:1)
您的代码存在一些问题。首先,你有一个缩进问题 - 在import foo.bar
foo.bar.my_method()
函数中y
获得'定义',在somefn()
之后,所以它实际上从来没有机会进入堆栈。您需要将return
重新定义为:
code
但这只是冰山一角。更大的问题是code = """def somefn(x):
return x + x
y = somefn(z)"""
无法修改函数的本地范围。这是因为Python不使用exec()
来查找本地范围内的变量,因此来自dict
的所有更改都不会反映回堆栈以启用查找。这会导致奇怪的问题,其中exec()
似乎更改了exec()
字典,但Python仍然会抛出locals()
:
NameError
这是一种预期的行为,如issue4831中所述,并在official docs进一步表述:
注意:默认的 locals 的行为与下面的函数
locals()
相同:对默认 locals 字典的修改不应该是尝试。如果您需要在函数exec()
返回后查看代码对 locals 的影响,请传递显式的 locals 字典。
但是如果你必须反映这些变化,你可以做一个post-exec本地范围更新:
def otherfn(codestr):
z = 2
exec(codestr)
print(locals()["y"]) # prints 4
return y # NameError
otherfn(code)