Injecting new names into the above frame
peter.waller at gmail.com
Fri Sep 12 14:44:57 CEST 2008
I know this will probably be perceived as 'evil voodoo', and fair
enough: it probably is. I guess it is unpythonic.
.. but I want to know how to do it anyway - mostly for my own
Consider the following snippet of code:
def Get( *names ):
if not names: return None
frame = sys._getframe(1)
prevFrameLocals = frame.f_locals
for name in names:
prevFrameLocals[ name ] = FetchObjectNamed( name )
Get("a", "b", "c")
print a, b, c
FetchObjectNamed() is an arbitrary function which takes a string and
returns an object it got from some store somewhere.
This works fine at the module level, because names in the locals/
globals dictionary can be played with in this way. The idea is to save
lots of typing, i.e.
a, b, c = Get("a","b","c")
..gets frustrating after much typing for many objects with long names.
This is just an example, there are other instances I have where it
would be nice to inject names into the frame above.
Of course, we hit a road block when we call 'Get' from a function
rather than a module, because the locals dictionary does not get
copied back into the code object automatically, so we have to add this
snippet before the Get() function returns:
from ctypes import pythonapi, py_object, c_int
pythonapi.PyFrame_LocalsToFast( py_object( frame ), 1 )
This copies back the names into the code object, and works fine.. that
is, if the names already exist within the code object.
a = None
print a # Works
print b # Name error, b is undefined
Is there any way for Get() to define a new variable within
MyFunction's code object? Or is there any programmatic way to, at
runtime, insert new names into functions?
I don't care how hacky it is and whether it requires making calls to
python's internals with ctypes - maybe the whole code object needs to
be replaced? is it even possible to do that when the Get() function is
about to return to this new code object?
More information about the Python-list