Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141411
  • 博文数量: 54
  • 博客积分: 2682
  • 博客等级: 少校
  • 技术积分: 580
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 20:56
文章分类
文章存档

2012年(2)

2011年(10)

2010年(28)

2009年(14)

我的朋友

分类: C/C++

2010-01-14 10:53:18

仔细看了《python源码剖析》这书的7,8章,觉得记载一些笔记,理清一下思路比较好。
 
看完第八章,按照自己的理解画了一个图。
 
 
 
《剖析》一书的前六章纯属基础,甚至可以当一个c课程设计来读。第六章作者的smallpython这个应用程序就是例子。
 
《剖析》第七章开始读的速度要放慢,因为进入了新的领域。而且个人感觉从这一章开始,由于源码的复杂性,作者引用源码的省略部分增多,造成读者阅读困难,个人感觉要对照项目自己看。
 
这本书大概是为了方便读者理解,采取的并不是python启动顺序的时间线来讲解,而是采取的从简单到复杂的方式讲解的。我这里换个方式,按照到目前为止我的理解,python启动顺序的时间线来讲解。
 
python运行时环境(也就是整个全局环境)的建立,7,8章并没有详解,那么我们就从python运行时环境建立后说起。
按我的理解,python运行时环境建立好后,会调用PyEval_EvalFrameEx(ceval.c)。
 
首先获取当前线程,在这里是一个
 
/* pystate.h */
typedef struct _ts {
        struct _ts *next;        /* 指向兄弟线程 */
        PyInterpreterState *interp;        /* 指向自己所处的进程 */
        struct _frame *frame;
        ...
        long thread_id;
} PyThreadState;
 
可以看到一个进程中的线程是用单向链表串起来的。
进程类PyInterpreterState于本文无太大关系,略去不讲。
我们看struct _frame *frame.
 
/* frameobject.h */
typedef struct _frame {
        ...
        struct _frame *f_back;
        PyCodeObject *f_code;
        PyObject *f_builtins;
        PyObject *f_globals;
        PyObject *f_locals;
        ...
        /* 栈空间 */
} PyFrameObject;
 
简单来理解,一个PyFrameObject就是一个Code Block, 一个Code Block就是一个名字空间,一个名字空间就是一个module或一个函数或一个类。 反正进入了一个地方后,变量名的所处环境要发生改变,这个地方就叫做Code Block。
 
比如
/* module1.py */
import sys
 
a = 1
 
def p():
        a = 2
        print a
 
p()
这个代码里有两个Code Block。一个是module本身,一个是p函数。
每段Code Block都对应有PyCodeObject。 这里面记录了这个Code Block的字节码。
每个Code Block都对应有PyFrameObject,这里面记录了栈帧信息。
举例来说:
调用p,是发生在module1里的。
所以p对应的PyFrameObject的f_back字段就指向module1对应的PyFrameObject。
 
还是回到PyEval_EvalFrameEx这个函数,这个函数把当前线程的frame字段指向需要执行的frame后,就开始逐个按序执行frame->f_code里的字节码。一个字节码其实是一个占一个byte的数字。python总共有140个左右的字节码。
 
从上面的图来看,从.py到PyCodeObject的过程属于编译过程,本书中没有做讲解。
现在要仔细看的是两个地方
1.从PyCodeObject到PyFrameObject的过程(也就是frameobject.c中的
PyFrameObject PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, PyObject *locals) 目前为止我猜想这个函数是被python运行时环境调用的)
2.生成PyFrameObject后,如何去执行。
PyObject *PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
这个函数位于ceval.c,是python虚拟机实现的核心部分。
 
阅读(1084) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~