我从外部(但受信任的)数据库接收python函数定义作为字符串。该字符串包含def fun(x):
形式的定义,以及可能在fun
定义中使用的其他函数定义。
我希望exec
代码,并使用fun
,如下所示:
def check_fun(code, first_terms):
exec(code)
good = all(fun(key) == value for (key, value) in first_terms)
return good
但是python抱怨:
SyntaxError: unqualified exec is not allowed in function 'check_fun' it contains a nested function with free variables
我该怎么办?
我看到答案https://stackoverflow.com/a/9195548/3001761,但我不明白。我尝试用
替换exec code
exec code in globals(), d
正如那里所建议的那样。此后打印d
告诉我fun
及其辅助函数现在位于d
,但执行fun
会引发NameError
...
我忘了补充说这是在Python 2.7中。
最后,这是我想要实现的一个例子:
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> code = 'def fun(x):\r\n return helper(x)\r\n\r\n\r\ndef helper(x):\r\n return "got it", x\r\n'
>>> print code
def fun(x):
return helper(x)
def helper(x):
return "got it", x
>>> exec code
>>> fun(1)
('got it', 1)
更新:
关注https://stackoverflow.com/a/872082/4680581后,我尝试了
def check_fun(code, first_terms):
exec code in globals(), globals()
good = all(fun(key) == value for (key, value) in first_terms)
return good
"工作"。当然,现在fun
最终会出现在全局命名空间中,这并不理想。如果我可以改变这一点,我就完成了。
解决方案:
def check_fun(code, first_terms):
new_code = ('def check(first_terms):\r\n '
+ code.replace('\r\n', '\r\n ')
+ '\r\n return all(fun(key) == value for (key, value) in first_terms)')
exec new_code
return check(first_terms)
看起来不错。 (我有点不喜欢对琴弦进行的修剪量,也许我仍然可以对此进行改进......)