Aurora Aurora - 1 year ago 44
Python Question

Returning a function of unknown name from within a function

code = "def foo(): return 'bar'"

def lol(code):
exec code
return foo

a = lol(code)
print a()

This works normally, but the problem starts when we don't know what the function in the string is called. If I can guarantee that the code will be small, with a single function, how can I return that function?

One solution I thought of was just requiring the function be called 'foo' etc, so I can just return that, but it feels ugly.



You could do it by explicitly specifying dictionaries exec should use for the global and local execution context. Afterwards the one used for locals should have a single entry for the function object, which can be returned without knowing its name since it should be the only item defined in the dictionary:

import types

def lol(code):
    globals_ = {"__builtins__": None}  # no built-ins for safety
    locals_ = {}

    exec(code, globals_, locals_)
    if len(locals_) != 1:
        raise ValueError("code defined more than one item")
    value = locals_.popitem()[1]  # get value of item defined
    if type(value) != types.FunctionType:
        raise ValueError("code didn't define a function")

    return value  # return function object that was defined

my_code = "def foo(): return 'bar'"
a = lol(my_code)