Right leg
Right leg

Reputation: 16730

Recompile Python bytecode instructions

Suppose I have a speak function:

def speak():
    print("moo")

I can disassemble it as one usually does, with dis.dis:

>>> dis.dis(speak)
  2           0 LOAD_GLOBAL              0 (print)
              3 LOAD_CONST               1 ('moo')
              6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
              9 POP_TOP
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE

But I want to destruct the code object associated with the speak function into a sequence of instructions, and then compile these back. With the help of dis.Bytecode, I can get a sequence of dis.Instructions that represents the code object:

>>> bytecode = dis.Bytecode(speak)
>>> for instruction in bytecode:
...     print(instruction)
... 
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=0, starts_line=2, is_jump_target=False)
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval='moo', argrepr="'moo'", offset=3, starts_line=None, is_jump_target=False)
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=6, starts_line=None, is_jump_target=False)
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=9, starts_line=None, is_jump_target=False)
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=10, starts_line=None, is_jump_target=False)
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=13, starts_line=None, is_jump_target=False)

Is there a straightforward way to compile these Instruction objects into the original code object?

For instance, I'm looking for a compile_back function that would take a sequence of instructions and output an executable code object:

>>> code_object = compile_back(dis.get_instructions(speak))
>>> exec(code_object)
moo

Upvotes: 2

Views: 745

Answers (1)

user2357112
user2357112

Reputation: 281594

The sequence of Instruction objects from dis.Bytecode is not enough to reconstruct a code object. A code object isn't just a sequence of instructions; it includes plenty of other data, like the argument count, the size of the evaluation stack, flags indicating various properties, etc. Most of these things are (briefly) described in a table in the inspect module docs, but there's even some "scratch space" not accessible through ordinary means.

Instruction objects would be enough to recover a lot of a code object's information, but not all. With some dangerous assumptions, you might be able to get something that usually works, but it'd be better to keep more of the information from the original code object in the first place.

In any case, there's no straightforward way.

Upvotes: 1

Related Questions