使用通过exec定义的函数

时间:2015-03-17 12:00:16

标签: python exec

我从外部(但受信任的)数据库接收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)

看起来不错。 (我有点不喜欢对琴弦进行的修剪量,也许我仍然可以对此进行改进......)

0 个答案:

没有答案