Python运行过程简单介绍

1.背景

编译:代码编程生成可执行文件,可执行文件不跨平台和架构,一次编译多次运行
  狭义上的编译是指从源码到机器码的过程,编译器比如GCC,MSVC
  广义上的编译是从一种代码到另一种代码(中间代码)
解释:无需编译直接执行,但是解释器不跨架构和平台

2.过程

Python运行过程简单介绍_第1张图片

1.编译

  虽然Python是一种解释性的语言,但实际上是先将Python代码编译成字节码(byte code),然后再执行,编译和解释执行都是使用CPython。编译过程与C语言的编译过程比较类似:

  1. 将Python源码分割为Token流
  2. 生成树形结构的Parser Tree
  3. 将Parse Tree转换为AST(抽象语法树,Abstract Syntax Tree)
  4. 构建符号表
  5. 根据AST和符号表生成code object

  每一个函数有一个code object,保存了函数的很多信息,其中co_code字段中保存了虚拟机指令的二进制表示(即byte code),将code object写入二进制文件(即.pyc文件)。

  程序运行时,code object保存再内存的PyCodeObject对象中,当程序运行结束时,将code object写入到.pyc文件中,下一次运行相同的程序时,Python会根据.pyc文件中的code object直接建立内存中的PyCodeObject对象,无需重新编译。

2.解释执行
(1). code object

  code object中byte code是二进制表示,反编译后可阅读,比如
Python运行过程简单介绍_第2张图片

  include/opcode.h中共有121个opcode,CPython解释器中有一个很大的循环,不停读入opcode执行对应的指令,对应的指令使用C实现,比如
Python运行过程简单介绍_第3张图片

(2). frame

  在源代码编译成PyCodeObject对象后,就有虚拟机负责剩下的运行,虚拟机会从PyCodeObject中读取byte code(Python虚拟机指令,不是CPU指令),并在当前上下文中执行,但是PyCodeObject中不包含程序执行时所需的动态信息(上下文信息),程序运行的动态信息包含在frame中。

  每次调用函数或者刚开始运行Python时,会建立一个新的frame(可以这么理解,但是CPython存在优化,比如惰性对象),并在这个frame环境下一条一条运行byte code,每一条byte code有相应的C语言代码执行。frame是一个栈结构,但是实现是用链表实现的,该frame记录了返回地址和pc值等关键值。

 
 

参考资料:

编译器和解释器的区别
深入理解Python虚拟机
Python Internal
CPython Internals
码农高天:不基础的python基础

你可能感兴趣的:(Python,python)