Python编译过程和执行原理

简介: hello,这里是Token_w的文章,主要讲解python的基础学习,希望对大家有所帮助整理不易,感觉还不错的可以点赞收藏评论支持,感谢!

hello,这里是Token_w的文章,主要讲解python的基础学习,希望对大家有所帮助

整理不易,感觉还不错的可以点赞收藏评论支持,感谢!



一. Python执行原理


这里的解释执行是相对于编译执行而言的。我们都知道,使用C/C++之类的编译性语言编写的程序,是需要从源文件转换成计算机使用的机器语言,经过链接器链接之后形成了二进制的可执行文件。运行该程序的时候,就可以把二进制程序从硬盘载入到内存中并运行。


但是对于Python而言,Python源码不需要编译成二进制代码,它可以直接从源代码运行程序。当我们运行Python文件程序的时候,Python解释器将源代码转换为字节码,然后再由Python解释器来执行这些字节码。这样,Python就不用担心程序的编译,库的链接加载等问题了。


对于Python解释语言,有以下3方面的特性:


  1. 每次运行都要进行转换成字节码,然后再有虚拟机把字节码转换成机器语言,最后才能在硬件上运行。与编译性语言相比,每次多出了编译和链接的过程,性能肯定会受到影响。


  1. 由于不用关心程序的编译和库的链接等问题,开发的工作也就更加轻松啦。


  1. Python代码与机器底层更远了,Python程序更加易于移植,基本上无需改动就能在多平台上运行。


在具体计算机上实现一种语言,首先要确定的是表示该语言语义解释的虚拟计算机,一个关键的问题是程序执行时的基本表示是实际计算机上的机器语言还是虚拟机的机器语言。这个问题决定了语言的实现。根据这个问题的回答,可以将程序设计语言划分为两大类:编译型语言和解释型语言。


  1. 编译实现的语言,如:C、C++、Fortran、Pascal、Ada。由编译型语言编写的源程序需要经过编译,汇编和链接才能输出目标代码,然后由机器执行目标代码。目标代码是有机器指令组成,不能独立运行,因为源程序中可能使用了一些汇编程序不能解释引用的库函数,而库函数又不在源程序中,此时还需要链接程序完成外部引用和目标模板调用的链接任务,最后才能输出可执行代码。


  1. 解释型语言,解释器不产生目标机器代码,而是产生中间代码,这种中间代码与机器代码不同,中间代码的解释是由软件支持的,不能直接使用在硬件上。该软件解释器通常会导致执行效率较低,用解释型语言编写的程序是由另一个可以理解中间代码的解释程序执行的。和编译的程序不同的是,解释程序的任务是逐一将源代码的语句解释成可执行的机器指令,不需要将源程序翻译成目标代码再执行。对于解释型语言,需要一个专门的解释器来执行该程序,每条语句只有在执行是才能被翻译,这种解释型语言每执行一次就翻译一次,因而效率低下。


  1. Java解释器,java很特殊,java是需要编译的,但是没有直接编译成机器语言,而是编译成字节码,然后在Java虚拟机上用解释的方式执行字节码。Python也使用了类似的方式,先将Python编译成Python字节码,然后由一个专门的Python字节码解释器负责解释执行字节码。


  1. Python是一门解释语言,但是出于效率的考虑,提供了一种编译的方法。编译之后就得到pyc文件,存储了字节码。Python这点和java很类似,但是java与Python不同的是,Python是一个解释型的语言,所以编译字节码不是一个强制的操作,事实上,编译是一个自动的过程,一般不会在意它的存在。编译成字节码可以节省加载模块的时间,提高效率。


  1. 除了效率之外,字节码的形式也增加了反向工程的难度,可以保护源代码。这个只是一定程度上的保护,反编译还是可以的。


二. Python内部执行过程


2.1 编译过程概述


当我们执行Python代码的时候,在Python解释器用四个过程“拆解”我们的代码,最终被CPU执行返回给用户。


首先当用户键入代码交给Python处理的时候会先进行词法分析,例如用户键入关键字或者当输入关键字有误时,都会被词法分析所触发,不正确的代码将不会被执行。


下一步Python会进行语法分析,例如当"for i in test:"中,test后面的冒号如果被写为其他符号,代码依旧不会被执行。


下面进入最关键的过程,在执行Python前,Python会生成.pyc文件,这个文件就是字节码,如果我们不小心修改了字节码,Python下次重新编译该程序时会和其上次生成的字节码文件进行比较,如果不匹配则会将被修改过的字节码文件进行覆盖,以确保每次编译后字节码的准确性。


那么什么是字节码?字节码在Python虚拟机程序里对应的是PyCodeObject对象。.pyc文件是字节码在磁盘上的表现形式。简单来说就是在编译代码的过程中,首先会将代码中的函数、类等对象分类处理,然后生成字节码文件。有了字节码文件,CPU可以直接识别字节码文件进行处理,接着Python就可执行了。


2.2 过程图解




2.3 编译字节码

Python中有一个内置函数compile(),可以将源文件编译成codeobject,首先看这个函数的说明:


compile(...) compile(source, filename, mode[, flags[, dont_inherit]]) -> code object

参数1:源文件的内容字符串

参数2:源文件名称

参数3:exec-编译module,single-编译一个声明,eval-编译一个表达式 一般使用前三个参数就够了

使用示例:


#src_file.py
#some function
def f(d=0):
    c=1
    print "hello"
a=9
b=8
f()
>>> a=open('src_file.py','r').read()    #命令行模式中打开源文件进行编译
>>> co=compile(a,'src_file','exec')
>>> type(co)
<type 'code'>    #编译出了codeobject对象


2.4 codeobject对象的属性


codeobject有哪些变量,接上节的内容分析一下:


print(co.co_names)   #所有的符号名称
# ('f', 'a', 'b')
print(co.co_name)#模块名、函数名、类名
# <module>
print(co.co_consts)  #常量集合、函数f和两个int常量a,b,d
# (0, <code object f at 0xb7273b18, file "src_file", line 2>, 9, 8, None)
print(co.co_consts[1].co_varnames)  #可以看到f函数也是一个codeobject,打印f中的局部变量
# ('c',)
print(co.co_code)  #字节码指令
# dZdZdZedS
print(co.co_consts[1].co_firstlineno)  #代码块在文件中的起始行号
# 2
print(co.co_stacksize)  #代码栈大小
# 2
print(co.co_filename)  #文件名
# src_file    #模块名、函数名、类名 

codeobject的co_code代表了字节码,这个字节码有什么含义?我们可以使用dis模块进行Python的反编译:


import dis
dis.dis(co)
print(output)
'''
 2        0 LOAD_CONST               0 (0)
          3 LOAD_CONST               1 (<code object f at 0xb7273b18, file "src_file", line 2>)
          6 MAKE_FUNCTION            1
          9 STORE_NAME               0 (f)
 5        12 LOAD_CONST              2 (9)
          15 STORE_NAME              1 (a)
 6        18 LOAD_CONST              3 (8)
          21 STORE_NAME              2 (b)
 7        24 LOAD_NAME               0 (f)
          27 CALL_FUNCTION           0
          30 POP_TOP             
          31 LOAD_CONST              4 (None)
          34 RETURN_VALUE '''

从反编译的结果来看,Python字节码其实是模仿的x86的汇编,将代码编译成一条一条的指令交给一个虚拟的cpu去执行。


  • 第一列:行号
  • 第二列:指令在代码块中的偏移量
  • 第三列:指令
  • 第四列:操作数
  • 第五列:操作数说明


目录
相关文章
|
3月前
|
机器学习/深度学习 Python
堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能
本文深入探讨了堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能。文章详细介绍了堆叠的实现步骤,包括数据准备、基础模型训练、新训练集构建及元学习器训练,并讨论了其优缺点。
157 3
|
3月前
|
机器学习/深度学习 算法 数据挖掘
线性回归模型的原理、实现及应用,特别是在 Python 中的实践
本文深入探讨了线性回归模型的原理、实现及应用,特别是在 Python 中的实践。线性回归假设因变量与自变量间存在线性关系,通过建立线性方程预测未知数据。文章介绍了模型的基本原理、实现步骤、Python 常用库(如 Scikit-learn 和 Statsmodels)、参数解释、优缺点及扩展应用,强调了其在数据分析中的重要性和局限性。
132 3
|
21天前
|
存储 缓存 Java
Python高性能编程:五种核心优化技术的原理与Python代码
Python在高性能应用场景中常因执行速度不及C、C++等编译型语言而受质疑,但通过合理利用标准库的优化特性,如`__slots__`机制、列表推导式、`@lru_cache`装饰器和生成器等,可以显著提升代码效率。本文详细介绍了这些实用的性能优化技术,帮助开发者在不牺牲代码质量的前提下提高程序性能。实验数据表明,这些优化方法能在内存使用和计算效率方面带来显著改进,适用于大规模数据处理、递归计算等场景。
58 5
Python高性能编程:五种核心优化技术的原理与Python代码
|
2月前
|
算法 数据处理 Python
高精度保形滤波器Savitzky-Golay的数学原理、Python实现与工程应用
Savitzky-Golay滤波器是一种基于局部多项式回归的数字滤波器,广泛应用于信号处理领域。它通过线性最小二乘法拟合低阶多项式到滑动窗口中的数据点,在降噪的同时保持信号的关键特征,如峰值和谷值。本文介绍了该滤波器的原理、实现及应用,展示了其在Python中的具体实现,并分析了不同参数对滤波效果的影响。适合需要保持信号特征的应用场景。
160 11
高精度保形滤波器Savitzky-Golay的数学原理、Python实现与工程应用
|
1月前
|
安全 数据挖掘 编译器
【01】优雅草央央逆向技术篇之逆向接口协议篇-如何用python逆向接口协议?python逆向接口协议的原理和步骤-优雅草央千澈
【01】优雅草央央逆向技术篇之逆向接口协议篇-如何用python逆向接口协议?python逆向接口协议的原理和步骤-优雅草央千澈
66 6
|
2月前
|
缓存 数据安全/隐私保护 Python
python装饰器底层原理
Python装饰器是一个强大的工具,可以在不修改原始函数代码的情况下,动态地增加功能。理解装饰器的底层原理,包括函数是对象、闭包和高阶函数,可以帮助我们更好地使用和编写装饰器。无论是用于日志记录、权限验证还是缓存,装饰器都可以显著提高代码的可维护性和复用性。
48 5
|
2月前
|
缓存 开发者 Python
深入探索Python中的装饰器:原理、应用与最佳实践####
本文作为技术性深度解析文章,旨在揭开Python装饰器背后的神秘面纱,通过剖析其工作原理、多样化的应用场景及实践中的最佳策略,为中高级Python开发者提供一份详尽的指南。不同于常规摘要的概括性介绍,本文摘要将直接以一段精炼的代码示例开篇,随后简要阐述文章的核心价值与读者预期收获,引领读者快速进入装饰器的世界。 ```python # 示例:一个简单的日志记录装饰器 def log_decorator(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__} with args: {a
56 2
|
3月前
|
机器学习/深度学习 人工智能 算法
强化学习在游戏AI中的应用,从基本原理、优势、应用场景到具体实现方法,以及Python在其中的作用
本文探讨了强化学习在游戏AI中的应用,从基本原理、优势、应用场景到具体实现方法,以及Python在其中的作用,通过案例分析展示了其潜力,并讨论了面临的挑战及未来发展趋势。强化学习正为游戏AI带来新的可能性。
208 4
|
3月前
|
搜索推荐 Python
快速排序的 Python 实践:从原理到优化,打造你的排序利器!
本文介绍了 Python 中的快速排序算法,从基本原理、实现代码到优化方法进行了详细探讨。快速排序采用分治策略,通过选择基准元素将数组分为两部分,递归排序。文章还对比了快速排序与冒泡排序的性能,展示了优化前后快速排序的差异。通过这些分析,帮助读者理解快速排序的优势及优化的重要性,从而在实际应用中选择合适的排序算法和优化策略,提升程序性能。
80 1
|
4月前
|
Rust 监控 编译器
解密 Python 如何调用 Rust 编译生成的动态链接库(一)
解密 Python 如何调用 Rust 编译生成的动态链接库(一)
99 2

热门文章

最新文章