Frame hacking

fumanchu fumanchu at amor.org
Wed Dec 13 11:49:40 EST 2006


George Sakkis wrote:
> Actually I thought about this and it would be more convenient in my
> case if I could change the "signature" of f to "def f(x,y)" so that I
> can pass positional arguments instead of a keywords (don't ask why).
> I've tried creating a new code object by tweaking co_varnames,
> co_argcount, co_nlocals and making a new function out of it but it
> doesn't work.. does co_code have to be changed as well, and if so, how?

Yes; since x and y then become locals and are looked up using LOAD_FAST
instead of LOAD_GLOBAL. Easiest approach: write the new function
yourself and pass it to dis.dis() and expreiment with the differences
in bytecode.

Here are some helpers I use for bytecode hacking (from the top of
http://projects.amor.org/dejavu/browser/trunk/codewalk.py):

from opcode import cmp_op, opname, opmap, HAVE_ARGUMENT
from types import CodeType, FunctionType, MethodType

from compiler.consts import *
CO_NOFREE = 0x0040


def named_opcodes(bits):
    """Change initial numeric opcode bits to their named
equivalents."""
    bitnums = []
    bits = iter(bits)
    for x in bits:
        bitnums.append(opname[x])
        if x >= HAVE_ARGUMENT:
            try:
                bitnums.append(bits.next())
                bitnums.append(bits.next())
            except StopIteration:
                break
    return bitnums

def numeric_opcodes(bits):
    """Change named opcode bits to their numeric equivalents."""
    bitnums = []
    for x in bits:
        if isinstance(x, basestring):
            x = opmap[x]
        bitnums.append(x)
    return bitnums

_deref_bytecode = numeric_opcodes(['LOAD_DEREF', 0, 0, 'RETURN_VALUE'])
# CodeType(argcount, nlocals, stacksize, flags, codestring, constants,
#          names, varnames, filename, name, firstlineno,
#          lnotab[, freevars[, cellvars]])
_derefblock = CodeType(0, 0, 1, 3, ''.join(map(chr, _deref_bytecode)),
                       (None,), ('cell',), (), '', '', 2, '',
('cell',))
def deref_cell(cell):
    """Return the value of 'cell' (an object from a func_closure)."""
    # FunctionType(code, globals[, name[, argdefs[, closure]]])
    return FunctionType(_derefblock, {}, "", (), (cell,))()


Robert Brewer
System Architect
Amor Ministries
fumanchu at amor.org




More information about the Python-list mailing list