`
java-mans
  • 浏览: 11420491 次
文章分类
社区版块
存档分类
最新评论

[笔记]PyCodeObject初探

 
阅读更多
在code.h中有PyCodeObject的定义:
/* Bytecode object */
typedef struct {
    PyObject_HEAD
    int co_argcount;          /* #arguments, except *args */
    int co_nlocals;           /* #local variables */
    int co_stacksize;         /* #entries needed for evaluation stack */
    int co_flags;       /* CO_..., see below */
    PyObject *co_code;        /* instruction opcodes */
    PyObject *co_consts;      /* list (constants used) */
    PyObject *co_names;       /* list of strings (names used) */
    PyObject *co_varnames;    /* tuple of strings (local variable names) */
    PyObject *co_freevars;    /* tuple of strings (free variable names) */
    PyObject *co_cellvars;      /* tuple of strings (cell variable names) */
    /* The rest doesn't count for hash/cmp */
    PyObject *co_filename;    /* string (where it was loaded from) */
    PyObject *co_name;        /* string (name, for reference) */
    int co_firstlineno;       /* first source line number */
    PyObject *co_lnotab;      /* string (encoding addr<->lineno mapping) See
                           Objects/lnotab_notes.txt for details. */
    void *co_zombieframe;     /* for optimization only (see frameobject.c) */
    PyObject *co_weakreflist;   /* to support weakrefs to code objects */
} PyCodeObject;

Python编译器在将源文件编译成pyc文件的过程中,会收集字符串、常量值、字节码等出现在源代码中的静态信息。这些信息可以保存在pyc文件中和PyCodeObejct(运行时)。pyc文件实际上就是储存着PyCodeObject。

如上定义,PyCodeObejct包含许多成员用来保存信息,各个成员的含义都有注释,分别是类型和含义。
每个名字空间(或者说作用域)都对应一个PyCodeObejct,以下面的代码为例:
class A:
    pass

def Foo(arg):
    i = arg
    print(i)

if __name__ == "__main__":
    a = A()
    Foo(1)


首先文件作用域(文件全局)对应一个PyCodeObject,而其中还有类A和函数Foo两个作用域,也对应着另外两个PyCodeObject。
将文件作用域对应的PyCodeObject的信息输入,可以得到如下信息:

<class 'code'>
0
0
3
64
b'Gd\x00\x00\x84\x00\x00d\x01\x00\x83\x02\x00Z\x00\x00d\x02\x00\x84\x00\x00Z\x01\x00e\x02\x00d\x03\x00k\x02\x00r;\x00e\x00\x00\x83\x00\x00Z\x03\x00e\x01\x00d\x04\x00\x83\x01\x00\x01n\x00\x00d\x05\x00S'
(<code object A at 0x0247E430, file "./demo.py", line 1>, 'A', <code object Foo at 0x0247E3E0, file "./demo.py", line 4>, '__main__', 1, None)
('A', 'Foo', '__name__', 'a')
()
()
()
./demo.py
<module>
1
b'\x10\x03\t\x04\x0c\x01\t\x01'



第一行是额外指定输入PyCodeObject的类型,接下来是按照PyCodeObject的成员定义顺序依次输出,分别表示:
未知参数个数
局部变量个数
栈空间
标志位
字节码
常量信息
符号信息
局部变量名集合
闭包需要用到的信息
嵌套函数所引用的局部变量名集合
源文件完整路径
该CodeBlock的名字
源文件中对应起始行
字节码与源文件中行号对应关系

可以看到在常量信息中还包含了A、Foo两个PyCodeObject,下面再输出Foo的信息以加深认识:

<class 'code'>
1
2
2
67
b'|\x00\x00}\x01\x00t\x00\x00|\x01\x00\x83\x01\x00\x01d\x00\x00S'
(None,)
('print',)
('arg', 'i')
()
()
./demo.py
Foo
4
b'\x00\x01\x06\x01'



以下是用来输出信息的代码:

source = open('./demo.py').read()
co = compile(source, './demo.py', 'exec')

#co = co.co_consts[2]

print(type(co))
print(co.co_argcount)
print(co.co_nlocals)
print(co.co_stacksize)
print(co.co_flags)
print(co.co_code)
print(co.co_consts)
print(co.co_names)
print(co.co_varnames)
print(co.co_freevars)
print(co.co_cellvars)
print(co.co_filename)
print(co.co_name)
print(co.co_firstlineno)
print(co.co_lnotab)





JasonLee 2011.08.20 13:56
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics