def foo():
a = 5
b = 7
print ('a + b =', a + b)
exec(foo.__code__)
it correctly prints a + b = 12 but the following does not print anything.
import inspect
def foo():
a = 5
b = 7
print ('a + b =', a + b)
source = inspect.getsource(foo)
foo_code = compile(source, '<string>', 'exec')
exec(foo_code) # does not print anything
I am not able to figure out why that happens as in both cases we are executing the same code object except that the latter is a code object created from compile.
inspect.getsource(foo) doesn’t work for me… I’m not sure why the difference, but would suggest printing source; does it contain the body of the function or does it contain the whole function including def foo():, in which case executing it will only define the function but not call it.
Because foo.__code__ is the bytecode for the implementation of the function itself.
Because foo_code is the bytecode for the process of creating the function and binding it to the name foo in whatever namespace. It loads an embedded code object (which is equivalent to the one you got from foo.__code__), and the string 'foo' and uses them to create a function object (using the string 'foo' for the __name__ and the code object for the __code__).
This is not so. Use the dis module to verify.
It won’t work at the REPL, because inspect.getsource uses the function’s .__code__.co_filename to look up the original .py file and copy source code out of it - but in this case there isn’t such a file and the filename is a dummy value. You can reproduce it by just using a multi-line string literal containing the source for the compile call.
It does indeed contain the whole function including the def line.