0

I receive python function definitions as strings from a foreign (but trusted) database. The string contains a definition of the form def fun(x):, and possibly other function definitions that might be used in the definition of fun.

I would like then to exec the code, and use fun, as follows:

def check_fun(code, first_terms):
    exec(code)
    good = all(fun(key) == value for (key, value) in first_terms)
    return good

But python complains:

SyntaxError: unqualified exec is not allowed in function 'check_fun' it contains a nested function with free variables

What should I do instead?

I saw the answer https://stackoverflow.com/a/9195548/3001761, but I do not understand it. I tried to replace exec code with

exec code in globals(), d

as suggested there. Printing d just thereafter tells me that fun and its helper functions are now in d, but executing fun raises a NameError...

I forgot to add that this is in Python 2.7.

Finally, here is an example of what I'd like to achieve:

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)

UPDATE:

Following https://stackoverflow.com/a/872082/4680581, I tried

def check_fun(code, first_terms):
    exec code in globals(), globals()
    good = all(fun(key) == value for (key, value) in first_terms)
    return good

which "works". Of course, now fun ends up in the global namespace, which is not ideal. If I can change this, I'd be done.

SOLUTION:

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)

looks OK. (I slightly dislike the amount of mangling done to the string, maybe I can still improve on this...)

Community
  • 1
  • 1

0 Answers0