Functions and code objects

Fuzzyman fuzzyman at gmail.com
Thu Jul 27 10:33:17 EDT 2006


Fuzzyman wrote:
> Fuzzyman wrote:
> > Hello all,
> >
> > I'm trying to extract the code object from a function, and exec it
> > without explicitly passing parameters.
> >
> > The code object 'knows' it expects to receive paramaters. It's
> > 'arg_count' attribute is readonly.
> >
> > How can I set the arg_count to 0, or pass parameters to the code object
> > when I exec it ?
> >
>
> Ok, so now I'm getting somewhere, without really knowing what I'm
> doing. Using the CodeType I can create a new code object with identical
> attributes, except an 'argcount' of 0.
>
> It doesn't quite work, so I probably need to set some of the attributes
> *differently*.
>
> The code I use is :
>
> >>> def f(x):
>  ...     print x
>  ...
> >>> c = f.func_code
> >>> CodeType = type(c)
> >>> a = CodeType(0, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code,
>  ...     c.co_consts, c.co_names, c.co_varnames, c.co_filename,
> c.co_name,
>  ...     c.co_firstlineno, c.co_lnotab, c.co_freevars, c.co_cellvars)
> >>> a
> <code object f at 01C707A0, file "<input>", line 1>
> >>> exec a
> Traceback (most recent call last):
>   File "<input>", line 1, in ?
>   File "<input>", line 2, in f
> UnboundLocalError: local variable 'x' referenced before assignment
>
> (the first argument, 0, becomes the 'arg_count' attribute)
>
> So the code object is still creating a local scope, and knows that x is
> a local variable. ('co_nlocals' and 'co_varnames' ?).
>
> I'd like to construct the code object so that it takes the parameters
> from the enclosing scope (the context I pass into exec I guess),
> without clobbering any local variables that may be defined in the code
> object.
>
> Anyone got any clues ?
>

*Damn* I've extracted the code object and told it that it has no
arguments. Executing the code object results in the function object !

The code object is obviously the code object for the function
definition. *sigh*

I was hoping I could get to the code object for the *body* of the
function. Looks like that won't be possible without dis-assembling the
bytecode or other tricks even more hackish than what I've already done.

For the record, the code  I was using was :

x = 3
def f(x):
    print x

CodeType = type(f.func_code)

def convert_function(f):
    code = f.func_code
    nlocals = max(code.co_nlocals - code.co_argcount, 0)
    newCode = CodeType(0, nlocals, code.co_stacksize, code.co_flags,
                       code.co_code, code.co_consts, code.co_names,
                       code.co_varnames, code.co_filename,
code.co_name,
                       code.co_firstlineno, code.co_lnotab,
code.co_freevars,
                       code.co_cellvars)
    return newCode

print convert_function(f)
exec convert_function(f)

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml




More information about the Python-list mailing list