Suppose I want to execute code, for example
value += 5
inside a namespace of my own (so the result is essentially mydict['value'] += 5). There’s a function exec(), but I have to pass a string there:
exec('value += 5', mydict)
and passing statements as strings seems strange (e.g. it’s not colorized that way).
Can it be done like:
def block():
value += 5
???(block, mydict)
? The obvious candidate for last line was exec(block.__code__, mydict), but no luck: it raises UnboundLocalError about value. I believe it basically executes block(), not the code inside block, so assignments aren’t easy – is that correct?
Of course, another possible solution would be to disassembly block.__code__…
FYI, I got the question because of this thread. Also, this is why some (me undecided) call for new syntax
using mydict:
value += 5
Note how this doesn’t throw error but doesn’t change mydict either:
def block(value = 0):
value += 5
block(**mydict)
You can pass bytecode instead of a string to
exec, you just need to make the right bytecode for the purpose:Specifically, …:
the load and store instructions must be of the _NAME persuasion, and this
compilemakes them so, while…:…code in a function is optimized to use the _FAST versions, and those don’t work on a dict passed to
exec. If you started somehow with a bytecode using the _FAST instructions, you could patch it to use the _NAME kind instead, e.g. with bytecodehacks or some similar approach.