从c语言层分析python的实现原理
python作为一门开源的、跨平台的脚本语言,其底层全部用c来实现,下面从c语言的角度来分析python的执行过程
1. python解释器
编译python源码后,会在根目录生成python程序,此程序就是python脚本的解释器,python解释器主要由语法解析、编译和执行三个模块组成
2. python语法解析模块
python语法解析模块负责把python字符串或脚本文件根据其语法解析成c语言的数据结构
3. python编译模块
python编译模块负责把解析后的数据结构转换成虚拟机可执行的字节码对象PyCodeObject
4. python执行模块
python执行模块负责执行python字节码,通常也叫做python虚拟机
当执行python file时,python首先会判断file是否为字节码文件,通常字节码文件的扩展名为pyc或pyo,而普通python脚本为py,判断的逻辑如下:
if (maybe_pyc_file(fp, filename, ext, closeit)) {
/* Try to run a pyc file. First, re-open in binary */
if (closeit)
fclose(fp);
if ((fp = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "python: Can't reopen .pyc file\n");
goto done;
}
/* Turn on optimization if a .pyo file is given */
if (strcmp(ext, ".pyo") == 0)
Py_OptimizeFlag = 1;
v = run_pyc_file(fp, filename, d, d, flags);
} else {
v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
closeit, flags);
}
若是字节码文件,则直接调用执行模块来执行,执行函数如下:
PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyCodeObject *co,
PyObject *globals,
PyObject *locals,
PyObject **args, int argc,
PyObject **kwds, int kwdc,
PyObject **defs, int defc,
PyObject *closure);
若是脚本文件,则先调用解析模块再调用编译模块,执行函数如下:
PyAPI_FUNC(struct _mod *) PyParser_ASTFromString(const char *, const char *,
int, PyCompilerFlags *flags,
PyArena *);
PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(FILE *, const char *, int,
char *, char *,
PyCompilerFlags *, int *,
PyArena *);
PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,
PyCompilerFlags *, PyArena *);
通常很多人会认为,编译后的python脚本会执行很快,但事实并非如此,编译后的字节码文件只是省去了语法解析和编译两部分,所以执行效率和普通python脚本一样,只是加载速度相对较快。目前由于个人能力有限,暂时大概分析了python的执行过程,至于语法解析、编译和执行的细节,逻辑比较复杂,待内功修炼到一定层次,再一一揭开python的神秘面纱