As a follow-up to this question I asked earlier, I'm experimenting with executing Python code as if it were in the context of an outer function. I do this by simply wrapping a block of code with def outer():
, and doing some simple string processing to properly indent the inner code. Then I compile it and execute the compiled inner code by executing the first code object in the co_consts
list.
Example:
mycode = """
print("Hey!")
"""
wrapped_code = 'def outer():\n ' + '\n '.join(mycode.strip().split('\n'))
compiled_code = compile(wrapped_code, '<str>', 'exec')
exec(compiled_code.co_consts[0], {}, {})
This executes the code print("Hey")
from within the context of an outer function. (If anyone is wondering why I'm doing this, it's part of a C extension module I've been working on.)
Question: A problem I run into is that if I wrap code in an outer function, and then execute the inner block of code, I don't seem to be able to pass any local variables to the execution context.
mycode = """
print(locals())
"""
wrapped_code = 'def outer():\n ' + '\n '.join(mycode.strip().split('\n'))
compiled_code = compile(wrapped_code, '<str>', 'exec')
exec(compiled_code.co_consts[0], {}, {"foo" : "bar"})
This outputs:
{}
Notice that I explicitly passed a local dict containing {"foo" : "bar"}
to exec
, yet when it actually executes the code and prints locals()
, it shows an empty dictionary. Why didn't Python use the dictionary of local variables I passed it?