Injecting new names into the above frame

Carsten Haese carsten.haese at gmail.com
Fri Sep 12 09:30:19 EDT 2008


Peter Waller wrote:
> 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.

Well, if you're really just asking out of curiosity, it should be
sufficient to tell you that this is not possible.

> [...] 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

The answer to why this doesn't work lies in the disassembly of that
function:
          0 LOAD_CONST          0 (0)
          3 STORE_FAST          0 (0)
          6 LOAD_GLOBAL         1 (1)
          9 LOAD_CONST          1 (1)
         12 CALL_FUNCTION       1
         15 POP_TOP
         16 LOAD_FAST           0 (0) <- This is a
         19 PRINT_ITEM
         20 PRINT_NEWLINE
         21 LOAD_GLOBAL         1 (1)
         24 LOAD_CONST          2 (2)
         27 CALL_FUNCTION       1
         30 POP_TOP
         31 LOAD_GLOBAL         2 (2) <- This is b
         34 PRINT_ITEM
         35 PRINT_NEWLINE
         36 LOAD_CONST          0 (0)
         39 RETURN_VALUE

Since you have an assignment to the name a, a is recognized as a local
name at compile time. b is not recognized as a local name at compile
time, so even if you inject a value for b into the locals dictionary,
the byte code still looks up the value as a global name.

> 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?

Not without making fundamental changes to Python itself. The fact that
this isn't possible is a feature, in my opinion. I like the fact that I
can call a function and be *absolutely certain* that it's not going to
pollute my local namespace.

Hope this helps,

--
Carsten Haese
http://informixdb.sourceforge.net



More information about the Python-list mailing list