《深入Python虚拟机》笔记2-鸟瞰之1

这一章主要介绍解释器如何执行一个Python程序。

当一个模块被当做参数传给Python的时候,例如python test.py,下面是发生的主要活动。

1. 初始化:main->Py_Main

2. 编译: 解析树生成->抽象语法树生成->字节码生成->字节码优化->代码对象生成

3. 解释:代码对象执行

Python可执行文件其实就是一个C程序,就像在Linux系统上可执行的其他程序一样,例如常见的helloworld程序。

C的运行时执行下面的操作:加载库,检查和设置环境变量,然后像其他C程序一样执行Python可执行文件的main方法。Python可执行文件的main程序在./Programs/python.c文件里,它主要负责一些初始化,例如复制命令行参数给模块,然后main函数调用./Programs/python.c文件里的Py_Main函数,该函数处理解析器的初始化过程-解析命令行参数,设置程序的flag,读取环境变量,运行钩子,完成hash随机化等等。作为初始化的一部分,pylifecycle.c里的Py_Initialize会被调用,它将处理解释器状态和线程状态的数据结构的初始化,这两种数据结构非常重要。

Python解释器的数据结构PyInterpreterState定义如下,主要是一些只想实际存储数据字段的指针。

1 typedef struct _is {

2

3 struct _is *next;

4 struct _ts *tstate_head;

5

7 PyObject *modules_by_index;

8 PyObject *sysdict;

9 PyObject *builtins;

10 PyObject *importlib;

11

12 PyObject *codec_search_path;

13 PyObject *codec_search_cache;

14 PyObject *codec_error_registry;

15 int codecs_initialized;

16 int fscodec_initialized;

17

18 PyObject *builtins_copy;

19 } PyInterpreterState;

1. *next只想其他的解释器实例,所以一个进程中可以有多个python解释器。

2. *tstate_head 指向主线程

3. modules, modules_by_index, sysdict, builtins and importlib这些呢都是自解释的,他们都是PyObject的实例,PyObject是Python虚拟机世界里所有对象的根类型。

4. *codec相关的字段帮助定位和加载编码,对解码相当有用。

程序的执行必须在线程中进行,线程的状态结构包含了一个线程执行python代码对象所需的所有信息,下面是线程数据结构的一部分

1 typedef struct _ts {

2 struct _ts *prev;

3 struct _ts *next;

4 PyInterpreterState *interp;

5

6 struct _frame *frame;

7 int recursion_depth;

8 char overflowed;

9

10 char recursion_critical;

11 int tracing;

12 int use_tracing;

13

14 Py_tracefunc c_profilefunc;

15 Py_tracefunc c_tracefunc;

16 PyObject *c_profileobj;

17 PyObject *c_traceobj;

18

19 PyObject *curexc_type;

20 PyObject *curexc_value;

21 PyObject *curexc_traceback;

22

23 PyObject *exc_type;

24 PyObject *exc_value;

25 PyObject *exc_traceback;

26

27 PyObject *dict; /* Stores per-thread state */

28 int gilstate_counter;

29

30 …

24 PyObject *exc_value;

31 } PyThreadState;