3

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)  
1
  • I've seen other answers, like this one where people have modified bytecode without using PyCode at all which might help you. Note esp the add_self() function. Commented Nov 6, 2012 at 13:53

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.