一个理解python执行过程的新视角

我曾经人云亦云的学到一句话:“程序员不应该局限于某种编程语言”,并奉为圭臬,现在想来惭愧。这句话在某些时候的确有一定的道理,但绝对不应该被不分情况的肆意宣扬。

比如,对一位需要亲自敲代码的一线程序员说这句话,就相当不负责任。

如果有人在做一个互联网前端的项目时打算用C语言实现,去问他的项目经理,他可能首先会疑惑为什么会有这么蠢的想法。而这位项目经理很可能曾经在某次给大家的培训或演讲中提到:优秀的程序员不应该局限于某种特定语言。

好吧,不给自己的低水平找借口了。

一、C程序员对python执行过程的惯性思维

对于大多数时间都使用C语言的程序员,刚开始接触python时,很可能会理所当然的有这样的认知:解释器将Python编译为机器码,或许中间还经历一个翻译成C语言的过程,最后交给计算机运行,是一个边编译,边运行的过程。这种理解可能是由于对C语言理解的惯性思维。编译型语言从开发到运行就基本是这样一个过程,只不过编译和运行被分开到两个不同时间段进行。

在很多情况下这样的理解不会有什么不良影响,并且看起来似乎是一种很合理的解释。但如果需要做C和python的混合编程,恐怕会需要更深一点的理解,甚至你需要去看一看解释器的源码实现。

随着我们对python的理解更深入一些,可能会了解到字节码,虚拟机这些概念,对python的执行过程的描述更加符合官方的解释,但依然会让新手对一些问题的理解有障碍。

二、现在站在解释器的角度来理解

前面的理解我们是完全站在python语言脚本的角度上,它好像是一个被等待加工的原材料,而解释器则是一个加工机器,负责将这个脚本加工为计算机可以理解的机器指令。

解释器是一个执行机器,等待着外部的指令;是一个已经被编译为机器码的程序,能够直接和计算机硬件打交道。当一条指令到来的时候(当然是它能够理解的指令),解释器就会按照指令操纵计算机硬件,来达到指令发送者的意图,完成之后再等待接收下一条指令,依次进行下去,直到指令被处理完毕。这个时候,程序员所开发的Python脚本就是指令的发送者。

随着我们站的角度不同,python脚本就从一个被加工的对象,变成了一位操纵机器的操作工。虽然可能有些不严谨,因为中间的具体过程被忽略了,比如字节码的流程,比如pyc文件如何解释,但这样的一个解释会让新手更好的理解一些问题。

三、于是就可以解释一些之前不太好解释的问题了

(1)用C/C++做的python扩展,究竟是以什么样的角色存在呢?

现在我们可以看出来,为python写扩展并不是给python脚本写扩展,而是为python解释器写扩展,这个扩展将作为解释器的一部分,使cpython(如果用的是这种解释器的话)的功能更丰富,除cpytnon内嵌的功能和第三方库外,你可以根据你的项目为cpython量身定做一个功能,你只需要在你的脚本中给python解释器下达命令,令其执行这个功能。而第三方库也是对python解释器的扩展。

(2)为什么不能像C语言那样通过修改你的python程序,就能使它实现真正的并发呢(暂不考虑调用接口解开GIL)?

因为python的官方解释器Cpython本身就不支持,作为真正的程序执行者,你无法通过你的指令改变这一既成事实,就像一个操作工改变不了机器的零件组成一样。

(3)C语言和python的关系究竟是怎样的?

经常有人说python的底层是由C实现的,其实更准确的说,python的官方解释器Cpython是由C实现的,Python程序只不过是被敲到文件里的文本,除了能被解释器理解以外,跟其他文本没什么区别。只有在Python文本给解释器下达指令以后,才能体现出C与Python的亲密关系。当然,如何处理计算机的内存,如何赋值,以什么类型存储等等都是由C语言所编写出来的Cpython程序决定的。

(4)Python也是C实现的,但为啥很多情况下,python比C慢?

那是因为Python解释器中的实现导致的,而跟python语言没直接关系。虽然解释器是用C实现,但是为了保证Python的便利性,必须做很多判断,牺牲很多C在内存处理方面的优势,以及多出很多运算等等。如果用C实现一个算法,只需在必要的地方增加判断以保证安全性,会根据不同的情况选择合适的内存类型存储等等。这和我前面的一篇文章,动态数据类型会使Python变慢这一点并不矛盾。因为动态数据类型的确使python变得更加方便灵活,而这种灵活是以增加判断,改变存储方式,增加计算量等为代价的。

(5)为什么有些时候用C写python扩展提不了速?

那可能是虽然用c语言实现,但是你仍然利用了Cpython中的数据类型,以及数据的存储方式,这跟Python解释器的处理方式一样,所以不会有明显的速度提升。

(6)如何让C中嵌入的python语言不依赖于本地python环境?

在C/C++中嵌入python时,通过链接Cpython相关的库得到可执行程序,将不依赖python环境。如果在编译过程中,只是引用了python动态库,而没有将所需的库链接到可执行文件中,将仍然需要依赖本地python环境。

当然还有很多问题,等涉及到了再补充。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值