[英]I'm trying to understand Python's exec() function
So I have a string which is a function like 所以我有一个像这样的函数的字符串
code = """def somefn(x):
return x + x
y = somefn(z)"""
and I am trying to run this in another function like 我试图在另一个函数中运行它
def otherfn(codestr):
z = 2
exec(codestr)
return y
otherfn(code)
but it gives me the error: 但这给了我错误:
Traceback (most recent call last): File "C:/Users/Admin/Desktop/heh.py", line 11, in otherfn(code) File "C:/Users/Admin/Desktop/heh.py", line 9, in otherfn return y NameError: name 'y' is not defined 追溯(最近一次通话最近):文件“ C:/Users/Admin/Desktop/heh.py”,第11行,在其他fn(代码)文件“ C:/Users/Admin/Desktop/heh.py”,第9行,在otherfn中返回y NameError:未定义名称'y'
it works fine outside the function like 它在功能之外工作正常
z=2 exec(codestr) print(y)
it finds y just fine but not sure why it is bugging out when it is in the function. 它发现y很好,但不确定为什么在函数中时会出现bug。
How can I fix this? 我怎样才能解决这个问题? Is it something to do with globals() and locals()? 与globals()和locals()有关吗? Using Python 3.6 btw. 使用Python 3.6 btw。
There are several problems with your code. 您的代码有几个问题。 First of all, you have an indentation problem - the y
gets 'defined' inside the somefn()
function, after the return
so it never actually gets the chance to get onto the stack. 首先,您有一个缩进问题y
在return
后在somefn()
函数内被“定义”,因此它实际上从未有机会进入堆栈。 You need to redefine your code
to : 您需要将code
重新定义为:
code = """def somefn(x):
return x + x
y = somefn(z)"""
But that's just the tip of the iceberg. 但这只是冰山一角。 The greater issue is that exec()
cannot modify the local scope of a function. 更大的问题是exec()
无法修改函数的局部范围。 This is due the fact that Python doesn't use a dict
for lookup of variables in the local scope so all changes from the exec()
do not get reflected back to the stack to enable lookup. 这是由于以下事实:Python在本地范围内不使用dict
来查找变量,因此exec()
所有更改都不会反映回堆栈以启用查找。 This causes a weird issue where exec()
seemingly changes the locals()
dictionary, but Python still throws a NameError
: 这引起了一个奇怪的问题,其中exec()
似乎改变了locals()
字典,但是Python仍然抛出NameError
:
def otherfn(codestr):
z = 2
exec(codestr)
print(locals()["y"]) # prints 4
return y # NameError
otherfn(code)
This is an intended behavior, as explained in the issue4831 , and further pontificated in the official docs : 这是预期的行为,如issue4831中所述,并在官方文档中进一步加以说明:
Note : The default locals act as described for function
locals()
below: modifications to the default locals dictionary should not be attempted. 注意 :默认本地语言的行为与下面对函数locals()
描述相同:不应尝试对默认本地语言字典进行修改。 Pass an explicit locals dictionary if you need to see effects of the code on locals after functionexec()
returns. 传递一个明确的当地人解释,如果你需要看后当地人的功能代码的作用exec()
的回报。
But if you have to reflect the changes you can just do a post-exec local scope update: 但是,如果您必须反映更改,则可以执行后执行本地范围更新:
def otherfn(codestr):
z = 2
locals_ = locals()
exec(codestr, globals(), locals_)
y = locals_["y"]
return y
otherfn(code)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.