Reputation: 16730
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.Instruction
s 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 exec
utable code object:
>>> code_object = compile_back(dis.get_instructions(speak))
>>> exec(code_object)
moo
Upvotes: 2
Views: 745
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