I'm working on a silly project in python that effectively implements a semi-REPL in a web-browser, and I'm stuck on how to cleanly dynamically evaluate code on-the-fly.
Basically, I have a web-form where the user enters a function, which should be then executed on the server.
The expected entry is a single function, with defined parameters. The function name, however, is not specified.
What I want is to get a string, such as:
def function_for_xxx(param_1, param_2, param_3):
<stuff goes here>
return interesting_value
and somehow convert that into a normal python function object (e.g. object of type <class 'function'>
).
I can limit the scope of the task somewhat:
Right now, I've experimented a bit with the compile()
and exec()
calls, but they appear to insert the exec()
ed code into the current local scope, which is non ideal. I'd really like the exec to be done without side effects like that, and just return a module or the bare function.
Ok, I figured out a workaround that is kind of hackish, but does what I want.
Basically, we can exploit the fact that we can specify the execution scope to exec()
calls by specifying the globals
parameter.
func_container = compile(func"\n", "<dynamic_functions_xxx>", "exec")
scope = {
<objects made available to the dynamic function>
}
exec(func_container, scope)
Objects defined in the func
string are now present in the scope
variable, with no side effects to the local namespace.
General comments apply here. If you can memoize the compile/exec process, doing so is probably a good idea (compiling is slow!).