PyCodeObject (虚拟机运行时,常量,环境,字节码信息)
1 | /* code.h */ |
pyc文件(PyCodeObject持久化)
1 | /*import.c*/ |
字节码
1 | 1 0 LOAD_CONST 0 ('A') |
- pyc文件是对PyCodeObject的持久化,存放在硬盘,包含了除字节码意外的其他参数。每次执行后会将pyCodeObject持久化下来 使用 python demo.py启动脚步,若demo.py中无import 不会持久化
PyFrameObject
1 | [frameobject.h] |
- python只有一个interpreter, 其中维护了一个或多个PyThreadState对象, 这些对象对应的线程轮流使用一个字节码执行引擎. 为了实现线程同步, python通过一个全局解释器锁GIL.
- 线程执行栈帧(PyFrameObject),PyFrameObject 对象也是一个变长对象, 每次创建PyFrameObject对象的大小可能是不一样的. 每个栈帧对象都维护了一个PyCodeObject对象,f_builtins, f_globals 和 f_locals 是3个独立的名字空间,
- LOAD_NAME 将以此从local, global, builtin 3个名字空间顺序查找, 如果都没找到说明名字未定义, 抛出异常, 终止python虚拟机的运行. 搜索规则也就是 LGB 规则.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26// 有删改
TARGET(LOAD_NAME) {
PyObject *name = GETITEM(names, oparg);
PyObject *locals = f->f_locals;
PyObject *v;
v = PyDict_GetItem(locals, name);
Py_XINCREF(v);
if (v == NULL) {
v = PyDict_GetItem(f->f_globals, name);
Py_XINCREF(v);
if (v == NULL) {
v = PyDict_GetItem(f->f_builtins, name);
if (v == NULL) {
format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG, name);
goto error;
}
Py_INCREF(v);
}
}
PUSH(v);
DISPATCH();
} - python的异常机制处理中, 最重要的是why所表示的虚拟机状态及PyFrameObject对象中f_blockstack里存放的PyTryBlock对象. 变量why将指明python虚拟机当前是否发生了异常, 而PyTryBlock对象则指示程序员是否为异常设置了 except 代码块和 finally 代码块. python虚拟机处理异常的过程就是 why 和 PyTryBlock 的共同作用下完成的.