How are names and function bodies stored in CPython Code Objects?

Viewed 157

I have a python script.

def hello(self):
    return 6
print hello()

Disassembling after compiling in CPython I get

>>> c = compile(open('hello.py').read(), 'hello.py', 'exec')
>>> import dis
>>> dis.dis(c)
  1           0 LOAD_CONST               0 (<code object hello at 0x1006c9230, file "hello.py", line 1>)
              3 MAKE_FUNCTION            0
              6 STORE_NAME               0 (hello)

  3           9 LOAD_NAME                0 (hello)
             12 CALL_FUNCTION            0
             15 PRINT_ITEM
             16 PRINT_NEWLINE
             17 LOAD_CONST               1 (None)
             20 RETURN_VALUE

I'm curious how the <code object hello at 0x1006c9230 ...> is stored inside the CPython code object. There is the co_code function but that only prints out the bytecode instructions. If I serialize the CPython code object I get

>>> import marshal
>>> marshal.dumps(c)
'c\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00@\x00\x00\x00s\x15\x00\x00\x00d\x00\x00\x84\x00\x00Z\x00\x00e\x00\x00\x83\x00\x00GHd\x01\x00S(\x02\x00\x00\x00c\x01\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00C\x00\x00\x00s\n\x00\x00\x00d\x01\x00}\x01\x00|\x01\x00S(\x02\x00\x00\x00Ni\x06\x00\x00\x00(\x00\x00\x00\x00(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x01\x00\x00\x00x(\x00\x00\x00\x00(\x00\x00\x00\x00s\x08\x00\x00\x00hello.pyt\x05\x00\x00\x00hello\x01\x00\x00\x00s\x04\x00\x00\x00\x00\x01\x06\x01N(\x01\x00\x00\x00R\x02\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x08\x00\x00\x00hello.pyt\x08\x00\x00\x00<module>\x01\x00\x00\x00s\x02\x00\x00\x00\t\x03'

I know that

def hello(self):
    return 6

is stored somewhere in the dump because if I change it to return 5, one byte in the dump switches from 6 to 5.

1) Is there a way I can access the function body from the CPython code object. The closest I can get it c.names but that only prints out a string. I'm assuming there behind the scenes it is a PyObject that is being serialized as a string. I would also like a confirmation that the function body is indeed stored in c.names.

2) Does marshal dump store the function as bytecode instructions or as a uncompiled literal? I'm leaning toward uncompiled literal as I searched for the opcode \x83 (RETURN_VALUE) and it only appears once in the dump. I believe this implies that there is only one return statement when there should be two: once to exit out of the function hello and once to return None for exiting the script.

Version

Python 2.7.13+ (heads/2.7:96f5020597, May 26 2017, 15:26:13)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
1 Answers
Related