Reputation: 6871
The following code produces bytecode output as string. I want to replace some lines of the bytecode and reassemble and exec it. Do I need something like the ByteCodeAssember or can I do this with PyCode New?
http://docs.python.org/2/c-api/code.html#PyCode_New
http://pypi.python.org/pypi/BytecodeAssembler
output
********** code **********
type: <type 'str'>
def test(a,b):
return a*b
test(2,3)
********** compiles into the bytecode **********
type: <type 'code'>
1 0 LOAD_CONST 0 (<code object test at 0x101d1ca30, file "<string>", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (test)
3 9 LOAD_NAME 0 (test)
12 LOAD_CONST 1 (2)
15 LOAD_CONST 2 (3)
18 CALL_FUNCTION 2
21 POP_TOP
22 LOAD_CONST 3 (None)
25 RETURN_VALUE 3
********** bytecode **********
'd\x00\x00\x84\x00\x00Z\x00\x00e\x00\x00d\x01\x00d\x02\x00\x83\x02\x00\x01d\x03\x00S'
code
import dis
import sys
import inspect
import new
class writer:
def __init__(self):
self.s = ""
def write(self,text):
#print ': ',text
self.s += text
#save stdout
origstdout = sys.stdout
w = writer()
sys.stdout = w
s = "def test(a,b):\n\treturn a*b\ntest(2,3)"
c = compile(s,'<string>','exec')
# dis calls stdout, so output is in w
bytecode = dis.dis(c)
sys.stdout = origstdout
def h(x):
print '*'*10 + '\t' + x + '\t' + '*'*10 + '\n'*1
h('code')
print 'type: '+str(type(s))
print s + '\n'
h('compiles into the bytecode')
print 'type: '+str(type(c))
print w.s
h('bytecode')
print repr(c.co_code)
Upvotes: 3
Views: 785
Reputation: 6871
Byteplay is a nice wrapper for python code objects. It has its own code class. Code objects is CPython specific and more complicated. To get started certainly better to play with byteplay first.
from byteplay import *
def foo():
x = 10
print 'inside ',x
return 42
c = Code.from_code(foo.func_code)
print c.code
ret = foo()
print 'outside: ',ret
c.code[10] = (LOAD_CONST,1000)
foo.func_code = c.to_code()
print '*'*20
print c.code
ret = foo()
print 'outside: ',ret
produces
4 1 LOAD_CONST 10
2 STORE_FAST x
5 4 LOAD_CONST 'inside '
5 PRINT_ITEM
6 LOAD_FAST x
7 PRINT_ITEM
8 PRINT_NEWLINE
6 10 LOAD_CONST 42
11 RETURN_VALUE
inside 10
outside: 42
********************
4 1 LOAD_CONST 10
2 STORE_FAST x
5 4 LOAD_CONST 'inside '
5 PRINT_ITEM
6 LOAD_FAST x
7 PRINT_ITEM
8 PRINT_NEWLINE
6 10 LOAD_CONST 1000
11 RETURN_VALUE
inside 10
outside: 1000
Upvotes: 2