读书笔记:LearningPython第五版 (第一、★二章: Python执行程序的过程)

重点:

  1. Python解释过程: source code --> byte code --> JVM
  2. JIT 加速原理: 执行的时候将 一部分byte code 编译成 机器代码,替换原来的代码
  3. 其他的Python实现: Cpython, JPython, IronPython, PyPy, Stackless…
  4. Frozen Binaries

Chap1: A Python Q&A Session

1.1 Downside

运行速度

简而言之,标准的python实现,是将源代码 编译成中间语言,叫做byte code, 然后再解释执行

为了提高python的运行速度的问题,可以将逻辑部分使用python编写,而在需要性能的部分使用 C/C++编写,然后再粘合,比如 著名的 numpy

1.2 Python能做什么

  • 系统编程
  • GUI:
    • tkinter
    • PMW( 基于tkinter)
    • wxPython(基于C++库)
    • Dabo(基于tkinter,wxPython等)
    • Qt的工具
  • Internet Scripting
  • Component Integration
  • Database Programming
    • pickle, PyMongo, SQLObject, SQLAlchemy
  • Rapid Prototyping
  • Numeric and Scientific Programming
    。。。

1.3 How Is Python Developed and Supported?

Python开发者在网上通过源代码控制系统协调工作,每一次的变化都以一种正式协议的方式,其中包括写 PEP(Python Enhancement Proposal) 或者其他文件。

1.4 Python的长处

  • 面向对象,面向过程,函数式编程
    • 函数式编程特色: generators, comprehensions, closures, maps, decorators, anonymous function lambdas, and first-class function objects
  • 免费
  • 可移植
  • 强大
  • 和其他语言混合
  • 易学易用

Chap2: How Python Runs Programs

2.1 Python 解释器

Python不仅是一门语言,也是一个编译器的名称。编译器是一个软件,用来执行其他的程序。当你写了一个Python程序时,python解释器能够阅读你的程序,并且执行这些命令。

当安装Python解释器的时候,它最少也包括了一个解释器程序和一些支持性library。

2.2 程序执行

2.2.1 从程序员角度

python程序只是文本文件。 python文件以.py结尾,但是从技术上来说,只有当文件被import的时候,才必须要求文件以.py结尾 。程序由解释器一行一行执行。

2.2.2 从Python的角度

当让Python去运行脚本的时候,python要先执行一些步骤,才能够真正的运行你的代码。具体来说,先将代码编译成一些叫做byte code的东西,然后将它交给virtual machine

a. Byte code compilation

Python内部在执行程序的时候,先将源代码编译成一种byte code的格式,byte code是一种底层的,和平台无关的源代码表示。一条python语句,会被转换成多条的byte code指令。 这种转换是为了提升执行速度——Byte code的运行比文本文件运行速度快很多

如果python进程拥有机器上的权限,那么它会把byte code安装在 .pyc结尾的中。

在Python3.2版本以前,运行了几次程序后,我们将能在源文件的同一个目录下,看到这些编译后的文件; 而在3.2开始之后的版本,Python把会把这些.pyc byte code放置在源文件目录下的__pycache__文件夹下,并且根据创建它们的python版本来命名他们,比如:script.cpython-33.pyc

检查是否需要重新编译:
无论在何种model(将在Chap21中细讲),下一次执行程序的时候,python会加载这些.pyc并且跳过编译过程,只要源文件没有在上一次编译后进行过更改,并且没有使用和上一次编译 不同的python版本运行过代码。 具体步骤如下:

  1. 源代码改变: Python会自动检查源文件的上一次修改时间,去和byte code内容作比较,来判断是否需要重新编译
  2. Python版本变更:python也会根据byte code中的python版本信息,来决定这次是否需要重新编译

Python如果没有写权限

程序仍然会正确运行,但是这些byte code会在产生之后,被读入内存中,然后在程序结束之后就被删除。

因为.pyc文件能加速启动时间,所以在大项目中,最好确保python有写权限。

Byte code能够独立于源代码, 如果没有源文件,只有.pyc文件,那么程序也能执行。

byte code只在被引入时产生
只有被import的文件,才会将对应的byte code保存到文件中,最顶级的脚本程序入口文件不会被保存到文件,只会在内存中使用。

b.The Python Virtual Machine (PVM)

当程序被编译之后,byte code就会交付给 Python Virtual Machine来运行。

graph LR
A[源文件] --编译--> B[Byte code]
B  --交给--> C[Python虚拟机]

PVM本身并不是一个别的程序,它不需要单独安装。PVM本身就是一个大的代码循环,遍历你的代码,一条条执行代码的操作,它是 Python运行的引擎。它是在Python系统中,真正执行脚本的组件。技术上来说,它是所谓Python Interpreter的最后一步。

c. Performance implications

Python代码不像完全编译的语言一样,直接编译成机器码,所以它的运行速度自然比机器代码要慢;但它因为有一步编译,所以它的执行速度又比纯解释性语言快。

The net effect is that pure Python code runs at speeds somewhere between those of a traditional compiled language and a traditional interpreted language

d. Development implications

python并不区分 开发环境 和 部署环境,记住Python只有Runtime

exec, eval等 built-ins, 能够读取字符串,将其当作python代码运行

2.3 Execution Model Variations

上面讲的python执行模式反映的是一种标准的python实现,但并不是一定的。随着时间变化,会有其他的模式出现。

2.3.1 Python实现 的Alternatives

最基本的5种Python语言实现: CPython, Jython, IronPython, Stackless, and PyPy

  1. CPython: 最标准的实现。
  2. Jython(JPython): Python的另一种实现,为的是让python和Java结合在一起。 JPython包括一些Java类, 它们能将Python代码编译成 Java字节码,然后给JVM运行。 不如CPython速度快和稳定
  3. IronPython: 和JPython差不多,是给 .NET用的
  4. Stackless–Python for concurrency: 重新实现的加强版CPython,为的是Concurrency, 更适合 coroutine,并且自己提供了microthreads,比python自己的 线程和进程更好。
  5. PyPy–Python for speed: a drop-in replacement for CPython, 为的是让一部分程序运行更快, 提供了 Just-in-Time(JIT)编译器以及更快快速的 Python实现,提供了 sandbox tool来运行不安全代码, 并且提供了之前Stackless的系统。Just-in-Time(JIT)编译器以及更快快速的 Python实现,提供了 sandbox tool来运行不安全代码, 并且提供了之前Stackless的系统。

JIT 是 JVM的一个扩展,它把部分的byte code直接转换成机器代码,为了提高速度。 它是在程序运行的时候做的转换操作,并没有一个 预编译过程,并且JIT也能够 通过跟踪程序中每个对象的数据类型, 把动态类型的Python创建为 明确类型的机器代码。

2.3.2 Execution Optimization Tools

CPython及其之前提到的其他Python实现,在实现的时候都差不多: 将源代码编译成 byte code, 然后再交给合适的 virtual machine执行。

其他系统,比如Cython hybrid, the Shed Skin C++ translator, and the just-in-time compilers in PyPy and Psyco,试着进一步的优化这种 基本运行模式。

  1. Cython (A Python/C hybrid): is a hybrid language that combines Python code with the ability to call C functions and use C type declarations for variables, parameters, and class attributes. 尝试将python代码编译成C代码。
  2. Shed Skin (A Python-to-C++ translator): 试着将Python代码转换成C++代码,再由电脑上的C++编译器来编译执行。
  3. Psyco (The original just-in-time compiler): 运行的时候将byte code进一步转换成machine code,并且记录了对象的数据类型。运行的时候,Psyco通过记录各种传递对象的类型信息,来产生最优化、最有效率的 机器代码。机器代码产生后,它们就会替换掉原来的那部分byte code来加快执行速度。 这个JIT和Java的JIT不同,它是一种Specializing JIT Compiler, 它根据程序具体使用到的类型,在不同的情况下产生不同的机器代码。

2.3.3 Frozen Binaries

有工具可以把Python程序直接打包成 可执行文件:

  1. py2exe
  2. PyInstaller
  3. py2app
  4. freeze
  5. cx_freeze

Frozen binaries 打包就是把Python编译出来的 byte codePVM,还有其他Python支持文件打包在一起。所以这个可执行文件中已经有了 Python环境,不需要机器本身自带环境了。

2.3.4 Future Possibility

  • 也许会有直接把Python代码编译成 机器代码
  • 也许会有新的 byte code格式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章