How do I get the return value when using Python exec on the code object of a function?

前端 未结 5 1798
再見小時候
再見小時候 2020-12-06 04:04

For testing purposes I want to directly execute a function defined inside of another function.

I can get to the code object of the child function, through the code (

相关标签:
5条回答
  • 2020-12-06 04:42

    Yes, you need to have the assignment within the exec statement:

    >>> def foo():
    ...     return 5
    ...
    >>> exec("a = foo()")
    >>> a
    5
    

    This probably isn't relevant for your case since its being used in controlled testing, but be careful with using exec with user defined input.

    0 讨论(0)
  • 2020-12-06 04:43

    A few years later, but the following snippet helped me:

    the_code = '''
    a = 1
    b = 2
    return_me = a + b
    '''
    
    loc = {}
    exec(the_code, globals(), loc)
    return_workaround = loc['return_me']
    print(return_workaround)  # 3
    

    exec() doesn't return anything itself, but you can pass a dict which has all the local variables stored in it after execution. By accessing it you have a something like a return.

    I hope it helps someone.

    0 讨论(0)
  • 2020-12-06 04:44

    Here's a way to return a value from exec'd code:

    def exec_and_return(expression):
        exec(f"""locals()['temp'] = {expression}""")
        return locals()['temp']
    

    I'd advise you to give an example of the problem you're trying to solve. Because I would only ever use this as a last resort.

    0 讨论(0)
  • 2020-12-06 04:54

    While this is the ugliest beast ever seen by mankind, this is how you can do it by using a global variable inside your exec call:

    def my_exec(code):
        exec('global i; i = %s' % code)
        global i
        return i
    

    This is misusing global variables to get your data across the border.

    >>> my_exec('1 + 2')
    3
    

    Needless to say that you should never allow any user inputs for the input of this function in there, as it poses an extreme security risk.

    0 讨论(0)
  • 2020-12-06 05:07

    Something like this can work:

    def outer():
        def inner(i):
            return i + 10
    
    
    for f in outer.func_code.co_consts:
        if getattr(f, 'co_name', None) == 'inner':
    
            inner = type(outer)(f, globals())
    
            # can also use `types` module for readability:
            # inner = types.FunctionType(f, globals())
    
            print inner(42) # 52
    

    The idea is to extract the code object from the inner function and create a new function based on it.

    Additional work is required when an inner function can contain free variables. You'll have to extract them as well and pass to the function constructor in the last argument (closure).

    0 讨论(0)
提交回复
热议问题