当前位置 博文首页 > zy010101博客:Python代码执行模型

    zy010101博客:Python代码执行模型

    作者:[db:作者] 时间:2021-06-11 18:07

    python代码执行过程

    在python程序运行时,python首先会编译生成“字节码”,之后将字节码发送到所谓的“虚拟机”上执行。

    字节码是一种低级的,与平台无关的表现形式。字节码可以提高执行速度,比起最初的源代码文件,字节码的运行效率高得多。

    在Python3.2之后,python在执行代码的时候会生成一个名为__pycache__的子目录,在该目录中存放一个名为“文件名+解释器+python版本+.pyc”的文件,这个文件就是字节码。

    在下一次运行python程序的时候,如果没有对源代码进行更改或者是python版本进行更改,那么python将会直接加载.pyc文件。

    源文件的改变:
    python会自动检查源文件和字节码文件最后一次修改的时间戳,来确认是否需要重新编译。
    python解释器版本的改变:
    .pyc文件的名称中含有python的版本,导入机制会检查名称中的python版本,来确认是否需要重新编译。
    

    最后,请记住字节码只针对哪些被导入(import)的文件而生成,而不是顶层的执行脚本。例如,我们有两个python代码,如下所示:

    # my.py文件内容
    from t import fun       # 从模块t导入fun函数
    fun()
    print("asda")
    
    # t.py文件内容
    def fun():
        print("Hello World!")
    

    现在执行my.py文件,就可以看到自动创建__pycache__目录,并且生成的.pyc文件名字为:

    t.cpython-38.pyc
    

    文件名中的t表明字节码确实只针对哪些被导入(import)的文件而生成,而不是顶层的执行脚本。cpython是我使用的python解释器,38表示我所使用的python版本是python3.8。

    python虚拟机

    字节码会被发送到python虚拟机(python virtual machine)上执行。PVM不是一个独立的程序,它是python的运行时引擎,它是python解释器的最后一步。

    python代码的执行过程应该是:

    源代码-->字节码-->PVM
    

    值得一提的是,python解释器和其他传统解释器不同,它包含了内部编译步骤。python并不需要反复重新解析源代码。这决定了python代码的执行速度还是可以的。

    在python中,我们只拥有运行时,因为编译器总是在运行时出现,并且是运行程序系统的一部分。因为python不需要预处理,编译,汇编,链接这些处理步骤。这就可以让python做到非常好的动态语言的体验。

    Python的各种实现

    CPython

    CPython是Python标准的实现。除了CPython之外,还有其他几种主要的Python实现。分别是:Jython,IronPython,PyPy等,其中Jython,IronPython能够提供直接和Java和.NET组件的使用接口。PyPy是一个现成的CPython替代品,它能更快的运行大多数的程序。

    CPython是最初的,标准的Python实现。它由ANSI C编写而成。你从python官网(https://www.python.org/)获取的Python就是CPython。绝大多数的Linux系统附带的Python也是CPython。

    Jython

    Jython是基于Java实现的Python,其目的是与Java集成。Jython将Python源代码编译成Java字节码,并将字节码发送到Java虚拟机(JVM)上执行。所以python代码在运行时就像真正的Java程序一样。
    Jython的目标是让python能够脚本化Java程序,以及Java程序可以将Python当作内嵌语言来运行。

    IronPython

    同样,IronPython的目的和Jython类似,是为了让python和.NET应用程序能够集成。IronPython项目起初由微软开发,后来将其开源。

    PyPy

    PyPy是CPython标准的另一个实现,它更加注重性能。它提供了一个带有即时编译器(JIT)的实现。即时编译器是指在运行代码的时候进行动态编译,而不是运行前编译好。JIT实际上是PVM的一个扩展,它将字节码中的部分直接编译为机器指令。因此,PyPy的性能将更好(几乎能跟C代码一样快),同时占用的内存可能更少。
    PyPy回避了垃圾回收(GC)机制,这导致它的非引用计数方案意味着临时文件不会立即关闭,甚至有时候需要手动释放。

    最后

    上述的Python运行时结构,目前看来是不太可能会有大的改变。因此,字节码依旧会是一种标准。Python不太可能真的去实现静态编译,这将会破坏python本身的设计。