python中print源码_Python解释器源码分析(二):print "Hello World"

目录node

本节以交互模式下执行print “Hello World”为例分析解释器的执行流程。

0x01 准备工做

打开Python-2.7.9\PCbuild目录下的visual studio解决方案pcbuild

设置python工程为启动工程

打开词法语法分析调试变量,python\pythonrun.c源码中修改int Py_DebugFlag = 1

编译python工程

0x02 运行输出

以Debug模式启动python工程,出现命令行提示窗口,输入print “Hello World”回车运行结果以下图所示。

316f7ae66f146f1e19aa7c755f37d8c1.png

0x03 主要流程分析

在解释器命令行窗口输入print “Hello World”回车后执行流程是怎样的呢? Python源码工程支持visual studio的编译和调试,加上visual studio很是强大的单步调试能力,所以对执行流程的分析基本没什么技术难度。这里简单总结下大体的运行流程,有兴趣的童鞋能够本身运行看看。

1 初始化

上一节中提到过Py_Main函数,它是python进程的入口函数,主要包括参数解析、初始化、运行等逻辑。初始化工做主要完成解释器的初始化,由Py_Main函数调用Py_Initialize函数完成,Py_Initialize函数位于Python\pythonrun.c源码文件内,初始化完成的主要流程以下图所示:

d5377f69d08d9c243a71c6cae4a6f1e9.png

1.1 数据类型准备

这里先看下数据类型准备_Py_ReadyTypes,类型的准备主要完成各类数据类型的准备工做。Python C源码中,全部内置的数据类型都是PyTypeObject结构体的一个实例,PyTypeObject结构体中以函数指针的形式,声明了各类处理函数,包括print、repr、hash、call、str、getattro、成员函数(tp_methods)、成员变量(tp_members)等。各个内置数据类型的定义在Objects目录下相应的C源码文件中,好比list数据类型实现的源码文件是Objects\listobject.c,在listobject.c源码文件中定义告终构体实例PyList_Type对象,以下图所示。

38a895ad2826b8717e35385cf55823bb.png

_Py_ReadyTypes函数主要调用Objects\typeobject.c\PyType_Ready函数对内置的数据类型的结构体对象的个元素进行初始化。

数据类型的初始化,主要完成对int、long、bytearray、float等数据类型的某些特定参数进行初始化。这里有一个东西没有搞明白,bytearray的初始化C函数,PyByteArray_Init函数什么事都没干直接返回1。

1.2 内置对象初始化

内置对象初始化,也就是__builtin__模块的初始化,经过调用Python\bltinmodule.c中的_PyBuiltin_Init函数完成内置常量、内置数据类型和函数的初始化。内置模块初始化包括两个动做,一是调用PyDict_SetItemString设置__builtin__模块的__dict__属性,二是调用Objects\object.c\_Py_AddToAllObjects函数将内置对象的结构体实例添加到双向循环链表refchain。代码以下图所示:

2d3542a3fbb8a172a571ea8eb1bf1a47.png

内置常量主要包括None、Ellipsis、NotImplemented、False、True。None、Ellipsis、NotImplemented在内存中的对象是PyObject结构体(在Include\object.h中定义)实例,True和False是PyIntObject结构体(在Include\intobject.h中定义)实例。

内置数据类型和函数,和内置常量的初始化动做同样。这里提一下,包括property、super、object、type、classmethod、staticmethod、str、file等内置对象都是PyTypeObject结构体(在Include\object.h中定义)实例。

2 运行

初始化完成后,进入交互模式。主要流程以下图。

d447451d44cc99427013e12522d25416.png

2.1 申请内存池

Python采用内存池的方式管理内存的使用,实现源码为Pyhon\pyarena.c。其主要思想是先在内存中申请一块内存,后续在该预先申请的内存块上分配相应的空间给对象使用。arena内存池的管理由两个结构体实现,_block和_arena。内存池管理机制后续进行分析。

67acb5864f30cd6ff32a1483c61f4085.png

2.2 词法及语法解析

词法及语法解析,主要调用Parse\parsetok.c\parsetok函数。该函数主要流程以下图所示。

ac69a7c21cb059981e04aa9885ef61e1.png

在交互命令行输入的print “Hello World”的单词解析信息存储在结构体parse_state结构体(在Parse\parser.h中定义)

2e7d05cc761f22d410f79479ab66be25.png

该结构体中有一颗解析树,该解析树存储了词法语法解析结果,各节点是_node类型的结构体。parsetok函数最终返回该解析树的top节点。值得注意的是,新解析出来的单词会做为最新的top节点,而且若是设置了编码方式,解析树的top节点是编码方式。

使用Parser\parser.c中的dumptree、showtree、printtree调试函数能够打印解析树。利用dumptree函数对parseok返回的解析树输出以下。

d87ecc83de5ab604fa95be9186ed50d5.png

词法语法解析完毕后,调用Parse\ast.c\PyAST_FromNode函数,将解析树各个节点由CST为AST(抽象语法树,Abstract Syntax Tree)。CST和AST都是语法分析的中间结果,不一样的地方是CST直接对应语法分析的匹配过程,含有大量的冗余信息,AST省略了大量冗余信息,直接对应实际的语义,也就是最终的分析结果。

Python为咱们提供了parse和ast模块,将其内部的单词和语法解析、字节编译暴露了出来。利用parse和ast模块,咱们能够访问python解析树。在python解释器命令行中导入模块parser,而后调用parser. suite(‘print “Hello World”’),能够看到解析结果和c函数dumptree的输出是同样的。一样使用ast模块的parse和dump函数能够看到ast解析结果。

import parser

cst = parser.suite('print "Hello World"')

print cst.tolist()

# [257, [267, [268, [269, [272, [1, 'print'], [304, [305, [306, [307, [308, [310, [311, [312, [313, [314, [315, [316, [317, [318, [3, '"Hello World"']]]]]]]]]]]]]]]]], [4, '']]], [4, ''], [0, '']]

import ast

astrst = ast.parse('print "Hello World"')

print ast.dump(astrst)

# Module(body=[Print(dest=None, values=[Str(s='Hello World')], nl=True)])

2.3 解析树节点类型

如2.2中描述,词法与语法分析的结果是一颗词法语法解析树,该树的各节点的结构体定义(在Include\node.h中)以下:

96314280020ddf2a32617c8cf8ed6863.png

那么节点类型有哪些呢?类型在Include\token.h及graminit.h两个头文件中给出了定义。例如257为文件输入、267为语句、268为单个语句、272为print语句、1为名称、310为表达式、312为AND表达式、3为字符串、4为新行、0为结束标志。

2.4 运行

运行主要调用Python\pythonrun.c\run_mod函数,其主要包括两个步骤,编译和执行。编译调用python\compile.c中的PyAST_Compile函数,对ast解析结果结构体mod_ty(在Include\Python-ast.h中定义)对象进行编译,返回代码结构体PyCodeObject(在Include\code.h中定义)对象,编译执行的具体实现细节后面再进行分析。另外,上述过程当中全部中间数据包括词法语法解析树、AST解析结果、编译等结果都存储在2.1所申请的内存池中。

33eae565e42dd6d612623a6cfc52f3f5.png

0x04 总结

本节简单分析了交互模式下print “Hello World”语句的执行流程,初步掌握了python解释器的工做流程。接下来会对内部一些核心的机制进行分析,包括arena内存池、单词解析、语法分析、编译、执行、全局锁等。

更多文章敬请关注

94390e1296a17242f04f0463ce2cab04.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值