标签:des style blog http color io os ar for
1.首先在code.h中查看PyCodeObject的struct
1 typedef struct { 2 PyObject_HEAD 3 int co_argcount; /* #arguments, except *args */ 4 int co_nlocals; /* #local variables */ 5 int co_stacksize; /* #entries needed for evaluation stack */ 6 int co_flags; /* CO_..., see below */ 7 PyObject *co_code; /* instruction opcodes */ 8 PyObject *co_consts; /* list (constants used) */ 9 PyObject *co_names; /* list of strings (names used) */ 10 PyObject *co_varnames; /* tuple of strings (local variable names) */ 11 PyObject *co_freevars; /* tuple of strings (free variable names) */ 12 PyObject *co_cellvars; /* tuple of strings (cell variable names) */ 13 /* The rest doesn‘t count for hash/cmp */ 14 PyObject *co_filename; /* string (where it was loaded from) */ 15 PyObject *co_name; /* string (name, for reference) */ 16 int co_firstlineno; /* first source line number */ 17 PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See 18 Objects/lnotab_notes.txt for details. */ 19 void *co_zombieframe; /* for optimization only (see frameobject.c) */ 20 PyObject *co_weakreflist; /* to support weakrefs to code objects */ 21 } PyCodeObject;
2.加载模块时,模块对应的PyCodeObject对象会被写入 .pyc中,当然在平时的运行代码的过程中,看不到 .pyc文件,
这个过程必须Python 中库函数compile,具体格式如:compile(source, filename, model[, flags[, dont_inherit]])
其中:
source是字符串或AST(abstract sytnax tree)对象.
filename是文件名,如果不是从文件中读出的代码,可传递一些可辨认的值
model是编译参数,有eval,signal,exec。处理的对象不同
后面参数可选
3.测试
(1)PyCodeObject
文件pycodeobject.py
1 #-*-codeing:UTF-8-*- 2 s = "hello the cruel world" 3 def func(): 4 print s 5 func()
在Python交互式shell里编译代码得到PyCodeObject对象:
>>> src = open("./code/pycodeobject.py").read() >>> co = compile(src,"pycodeobject.py",‘exec‘) >>> dir(co) [‘__class__‘, ‘__cmp__‘, ‘__delattr__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__le__‘, ‘__lt__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘co_argcount‘, ‘co_cellvars‘, ‘co_code‘, ‘co_consts‘, ‘co_filename‘, ‘co_firstlineno‘, ‘co_flags‘, ‘co_freevars‘, ‘co_lnotab‘, ‘co_name‘, ‘co_names‘, ‘co_nlocals‘, ‘co_stacksize‘, ‘co_varnames‘] >>>
pycodeobjec.py的PyCodeObject对象,print即可
>>> print co.co_argcount 0 >>> print co.co_nlocals 0 >>> print co.co_names (‘s‘, ‘func‘) >>> print co.co_varnames () >>> print co.co_consts (‘hello the cruel world‘, <code object func at 02118A88, file "pycodeobject.py", line 3>, None) >>> print co.co_code d
解析指令序列
>>> import dis >>> print dis.dis(co) 2 0 LOAD_CONST 0 (‘hello the cruel world‘) 3 STORE_NAME 0 (s) 3 6 LOAD_CONST 1 (<code object func at 02118A88, file "pycodeobject.py", line 3>) 9 MAKE_FUNCTION 0 12 STORE_NAME 1 (func) 5 15 LOAD_NAME 1 (func) 18 CALL_FUNCTION 0 21 POP_TOP 22 LOAD_CONST 2 (None) 25 RETURN_VALUE None >>>
第一列表示以下几个指令在py文件中的行号;
第二列是该指令在指令序列co_code里的偏移量;
第三列是指令opcode的名称,分为有操作数和无操作数两种,opcode在指令序列中是一个字节的整数;
第四列是操作数oparg,在指令序列中占两个字节,基本都是co_consts或者co_names的下标;
第五列带括号的是操作数说明。
(3)PyFrameObject
在frameobject.h查看PyFrameObject对象的数据结构
1 typedef struct _frame { 2 PyObject_VAR_HEAD 3 struct _frame *f_back; /* previous frame, or NULL */ 4 PyCodeObject *f_code; /* code segment */ 5 PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ 6 PyObject *f_globals; /* global symbol table (PyDictObject) */ 7 PyObject *f_locals; /* local symbol table (any mapping) */ 8 PyObject **f_valuestack; /* points after the last local */ 9 /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. 10 Frame evaluation usually NULLs it, but a frame that yields sets it 11 to the current stack top. */ 12 PyObject **f_stacktop; 13 PyObject *f_trace; /* Trace function */ 14 15 /* If an exception is raised in this frame, the next three are used to 16 * record the exception info (if any) originally in the thread state. See 17 * comments before set_exc_info() -- it‘s not obvious. 18 * Invariant: if _type is NULL, then so are _value and _traceback. 19 * Desired invariant: all three are NULL, or all three are non-NULL. That 20 * one isn‘t currently true, but "should be". 21 */ 22 PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; 23 24 PyThreadState *f_tstate; 25 int f_lasti; /* Last instruction if called */ 26 /* Call PyFrame_GetLineNumber() instead of reading this field 27 directly. As of 2.3 f_lineno is only valid when tracing is 28 active (i.e. when f_trace is set). At other times we use 29 PyCode_Addr2Line to calculate the line from the current 30 bytecode index. */ 31 int f_lineno; /* Current line number */ 32 int f_iblock; /* index in f_blockstack */ 33 PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ 34 PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ 35 } PyFrameObject;
查看栈帧
1 def func(): 2 import sys 3 frame = sys._getframe() 4 print frame.f_locals 5 print frame.f_globals 6 print frame.f_back.f_locals 7 #你可以打印frame的各个域 8 print s
此次的代码解析来自Python 2.7版本。
标签:des style blog http color io os ar for
原文地址:http://www.cnblogs.com/sxmcACM/p/4034214.html