关于python:组装字节码 – PyCode新

Assembling Bytecode - PyCode New

以下代码以字符串形式生成字节码输出。我想替换一些字节码行,重新组装并执行它。我需要像字节数字那样的东西吗?或者我可以用新的pycode来做这个吗?

http://docs.python.org/2/c-api/code.html_pycode_new

http://pypi.python.org/pypi/bytecodeassembler

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
**********      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'

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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):
\treturn a*b
test(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 + '
'
*1                                                                

h('code')                                                                                                            
print 'type: '+str(type(s))                                                                                          
print s + '
'
                                                                                                     

h('compiles into the bytecode')                                                                                      
print 'type: '+str(type(c))                                                                                          
print w.s

h('bytecode')                                                                                                        
print repr(c.co_code)


BytePlay是一个很好的Python代码对象包装器。它有自己的代码类。代码对象是特定于cpython的,并且更复杂。开始的时候最好先玩byteplay。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

生产

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  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