exec statement with/without prior compile
-
05-09-2019 - |
Question
These weekend I've been tearing down to pieces Michele Simionato's decorator module, that builds signature-preserving decorators. At the heart of it all there is a dynamically generated function, which works something similar to this...
src = """def function(a,b,c) :\n return _caller_(a,b,c)\n"""
evaldict = {'_caller_' : _caller_}
code = compile(src, '<string>', 'single')
exec code in evaldict
new_func = evaldict[function]
I have found, fooling around with this code, that the compile step can be completely avoided and go for a single:
exec src in evaldict
Now, I'm sure there is a good reason for that additional step, but I haven't been able to find what the difference between both approaches is. Performance?
And since I'm asking, could something similar, i.e. define a new function and get a handle to it, be achieved with eval? I tried, but couldn't get that to work...
Solution
There are a few differences that I see. Firstly, compile
has slightly better semantics in the face of syntax errors than exec
. I suspect that the real reason is that the definition of compile
is very explicit with respect to the handling of new line characters where exec
is a little less precise.
I was curious as to why compile
and exec
where being used in lieu of inner functions. I didn't know that compile
/exec
lets you control what globals are available. Very interesting.
OTHER TIPS
compile() allows you to control the code object created and its name and source, while exec is not so flexible. it is also worth doing so that others, when reading your code, will learn they are separate steps and have this in mind later, when they need to exec the same code more than once (where compile() once, exec multiple times would be faster), and writing your code to educate the next who reads it is always a worthy influence on design choices.