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...)