P
Peter Waller
Dear Pythoners,
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
interest.
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.
def MyFunction():
a = None
Get("a")
print a # Works
Get("b")
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?
Cheers,
- Peter
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
interest.
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.
def MyFunction():
a = None
Get("a")
print a # Works
Get("b")
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?
Cheers,
- Peter