组装字节码 - PyCode新

时间:2012-11-06 13:16:15

标签: python

以下代码将字节码输出生成为字符串。我想替换字节码的一些行并重新组装并执行它。我需要像ByteCodeAssember这样的东西,还是可以用PyCode New做这个?

http://docs.python.org/2/c-api/code.html#PyCode_New

http://pypi.python.org/pypi/BytecodeAssembler

输出

**********      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'

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)  

1 个答案:

答案 0 :(得分:2)

Byteplay是python代码对象的一个​​很好的包装器。它有自己的代码类。代码对象是CPython特有的,而且更复杂。首先要开始使用byteplay,最好先上手。

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  

产生

  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