Python是出类拔萃的

然而,这是一句非常模棱两可的话。这里的"Python"到底指的是什么? 是Python的抽象接口吗?是Python的通用实现CPython吗(不要把CPython跟Cython搞混了)?亦或者指的完全是其他的东西呢?可能我另外指的是Jython,或者IronPython,或者是PyPy。也或者转而谈论的又是RPython或者RubyPython(这两者是完全不同的东西)。

上面提到的那些技术经常被提起和引用, 它们的使用目的和场景是完全不一样的(至少,它们的操作方式是完全不一样的)

自从我使用Python工作以来,我已经用过了各种各样的.*ython工具了。但是直到最近我才花时间去理解到底它们是干嘛的,它们是怎样工作的,为什么它们是不可或缺的。

在这篇文章里面,我会介绍各种Python的实现,最后以对PyPy的介绍结尾, 因为我个人认为它是Python的未来。

所有的都从理解什么是"Python"开始。

如果你对机器码,虚拟机之类的很熟了,你可以跳过开头,直接从 "即时编译: PyPy和它的未来" 这部分开始看起。

Python是解释型的还是编译型的?

这是个Python新人都会迷惑的问题。

首先需要明了的是Python只是一个接口。有一个关于Python应该做什么以及怎么做的具体说明(就像其他任何接口一样 ),并且对应的有很多具体的实现(也像其他接口一样)。

其次需要知道的是“解释型”和“编译型”是具体实现的特性,而不是接口的特性。

所以,这个问题本身就没有组织好。

Python是解释型还是编译型的?这个问题真的没有组织好。

对使用最广泛的实现(CPython:用C实现的,通常简单的说成Python,若你不知道我所说的这些,那很肯能你在使用的就是CPython)而言,这个问题的答案是:解释型,但带有一些编译型特征。CPython把Python源码编译*成字节码,之后再解释这些字节码,执行之。

*注意:这个编译不是通常意义上的编译。通常我们说的编译,是指把高级语言代码转换成机器码。但这里实际上是一种种类的编译。(译者,这句话不是很懂,原文是it is a ‘compilation’ of sorts,不知作何解,求教各位读者。)

再详细看下上面的答案吧,这有助于我们理解本文中后面会讲到的几个概念。

字节码 vs. 机器码

了解字节码和机器码(或者native code)的区别是很重要的,最好的办法或许是看看例子:

C代码被编译成机器码,将在处理器上直接执行。每一条指令控制CPU工作。

Java代码被编译成字节码,将在Java虚拟机(JVM)这个抽象的计算机上执行。每一条指令由JVM处理,JVM同计算机本身之间交互。

简而言之:机器码快的多,但字节码更易迁移,也更安全。

机器码随机器的变化而变化,但字节码在所有的机器上都是一样的。有人可能会认为机器码是对特定环境优化了的。

回到CPython,工具链的执行过程如下:

CPython编译你的Python源代码,生成字节码。

字节码随后在CPython虚拟机上执行。

初学者常常因为看到.pyc文件而假设Python是编译型的。这也有一些合理性:.pyc文件正式之后要解释的字节码文件。所以,你若之前运行过你的Python代码,生成了.pyc文件,再次运行时就要快得多,因为不需要再次编译生成字节码了。

可选的虚拟机:Jython,IronPython等

正如我之前所述,Python有很多实现。前面也提到,CPython是最通用的。这是一个用C实现的,被认为是”默认“的实现。

但其他的呢?其中最显赫的之一就是Jython,一个用Java实现的采用了JVM的实现。CPython生成在CPython虚拟机上运行的字节码,而Jython生成在JVM上运行的java字节码(这同编译Java程序生成java字节码的过程是一样的)。

”为啥你要用其他的实现?”,你可能会如此发问。好吧,对开发者而言,不同的实现对不同的技术难题的支持程度不一样。

CPython中很容易为你的Python代码写C扩展,因为最终都是由C解释器执行的。另一方面,Jython则使得和其他java程序共同工作很容易:无需其他工作,你就可导入任何Java类,在你的Jython程序中使用其他Java类。(题外话,若你没有认真思考,这一段会很难。此时我们已经在讨论把不同语言的代码混在一起,并编译成同一程序。(提出混合Fortran和C代码编程已经有一段时间了。所以,这并不新鲜,但仍然很酷。))

下面是一个例子,一段合法的Jython代码:

[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_51

>>> from java.util import HashSet

>>> s = HashSet(5)

>>> s.add("Foo")

>>> s.add("Bar")

>>> s

[Foo, Bar]

IronPython是另一很流行的Python 实现,完全用C#实现,针对.NET平台。她运行在可以叫做.NET虚拟机的平台上,这是微软的

你可能会说,Jython:Java::IronPython:C#。它们各自运行在相同的虚拟机上,你能从你的IronPython中导入C#的类,从你写的Jython代码中带入Java类,等等

你完全可以不用任何非CPython的实现就能完成你手上的任何工作。但是使用这些技术也是有很多的好处的,大部分取决于你现在所使用的技术栈。 你使用了很多基于JVM的语言?Jython就是为你准备的。使用的都是.NET世界的语言?那么你应该试试IronPython了(或许你已经在用了)

顺便说一下(尽管这不是使用不同的实现的理由),注意Python的各种实现在对待你的Python源码的时候所做的处理方式是完全不一样的。然后这些差异是很小的,由于这些实现都在不停的发展改进中,随着时间的推移,这些差异会慢慢融合和兼容。比如,IronPython默认情况下使用Unicode字符串,但是在2.x版本的CPython中默认是ASCII字符串(如果使用了非ASCII字符串,会抛出一个UnicodeEncodeError错误),但是在3.x版本里面CPythong已经默认支持Unicode字符串了。

即时编译: PyPy和它的未来

我们已经有了一个使用C写的Python实现,一个用Java写的,一个用C#写的。接下来就是:用Python写的Python实现(有心人可能会注意这句话有点问题,是个死循环,^_^)

接下来我们看下什么地方容易搞混淆。首先,我们讨论下即时编译器JIT

JIT: 为什么会有这个?它的原理是什么?

大家都知道本地机器码的速度比字节码的速度快很多。那么,如果我们能将一些字节码直接编译成本地机器码再去运行它会怎样呢?我们必须花费一些代价(比如时间)在编译字节码到本地机器码上,如果最终的运行时间更快,那么这个代价就是值得的。这就是JIT编译器的动机,一种混合了解释器和编译器好处的技术。简单来讲,JIT就是想通过编译技术提升脚本解释器系统的速度。

例如, 被JIT(及时编译)采用的通用方法:

标识被经常执行的字节码。

把其编译成本地的机器码。

缓存该结果。

当同样的的字节码再次被执行的时候,会取预编译的机器码,得到好处(例如速度提升)。

这是关于PyPy的用处: 把JIT代入Python语言 (参看前面成果的附录).当然也有其他目的: PyPy 目标是成为一个跨平台,轻内存,支持stackless(译注:stackless为python提供微线程扩展,具有并发特性)。 但是及时编译才是它真正的卖点。 基于一系列时间测试的平均, 据说性能上能提高6.27倍. 停一下, 看看下面这个由PyPy Speed Center提供的图表:

PyPy is Hard to Understand

PyPy具有巨大的潜力,在这一点上,它与CPython高度兼容所以它能运行Flask,Django等等)。

但关于PyPy有许多困惑 (例如,荒谬的建议创造一种PyPyPy…语言). 按我的观点,那主要是因为PyPy实际上是两种东西:

一种用RPython(非Python (我之前撒谎了))编写的Python解释器。 RPython是Python的子集,具有静态类型。在Python里,最难严格推论类型 (为什么这么困难,考虑下下面的事实:

x = random.choice([1, "foo"])

将是合法的Python代码 (归功于Ademan).x的类型是什么? 我们怎么推出变量的类型,当类型还没有被严格实施?)通过RPython,你牺牲了一些灵活性, 但使得内存管理和优化大大的容易。

一个编译RPython代码为了各种目标和加入及时编译的编译器。默认平台是C,也就是从RPython到C编译器,但你也可以瞄准JVM或者其他。

只为清晰,我将引用这些PyPy(1)和PyPy(2)。

为什么你在同一层面下同时需要这两者? 你可以这样想一下:PyPy(1)是一个用RPython写的解释器,因此它能加载用户的Python代码并将它编译成字节码。但是这个用RPython写的解释器本身要能运行,就必须要被另外一个Python实现去解释,对不?

我们可以直接用CPython去运行这个解释器。但是这个还不够快

取而代之,我们使用了PyPy(2)(参考 RPython的工具链)去编译这个PyPy的解释器,生成其他平台(比如C, JVM或CLI)代码在我们的机器上运行,并且还加入了JIT特性。这个很神奇:PyPy动态的将JIT加入一个解释器,生成它自己编译器!(这就是核心原理:我们在编译一个解释器,并同时加入了另外一个单独的编译器到里面去)。

最终结果就是一个融合了JIT优化特性的单独的可执行文件,用来解释执行我们的Python源代码。这就是我们之前想要达到的效果。这么讲可能比较拗口,下面这张图可能会解释的比较清楚点:

再次重申下,PyPy真正可贵之处在于我们可以利用RPython实现各种不同的Python解释器,不用去关心JIT(除了一些小的提示外)。PyPy到时候会利用RPython工具链/PyPy(2)为我们自动实现JIT

事实上,我们还可以更抽象一点,我们理论上可以写一个适用于任何语言的解释器,然后将它扔给PyPy,最后获得那种语言的JIT。原因是PyPy仅仅关心的是优化解释器,而不会去关心这个解释器到底解释的是什么语言。

理论上你自己可以写一个适用于任何语言的解释器,然后将这个解释器传给PyPy,最后你得到这个语言的一个JIT。一个简单的题外话,我这里想提一下,JIT本事是相当棒的。它使用了一种叫做跟踪的技术,按照下面的步骤执行:

执行解释器并解释执行所有代码(还没有加入JIT特性)

对被解释过的代码做一些记录

确认你已经执行过的操作

将确认过的这些代码编译成本地机器码

想获取更多信息,可以参考这篇文章,易于理解,并且非常有趣

最后收尾:我们使用PyPy的RPython-to-C(或者其他目标平台)编译器去编译PyPy的基于RPython实现的解释器。

结尾

为什么它如此的伟大?为什么这个疯狂的想法值得我们去追求?我想Alex Gaynor已经在他的博客上面做了很好的解释了:“[PyPy就是未来] 因为[它]提供了更快的速度,更大的灵活性,并且对于Python的成长也提供了一个更好的平台”

总之:

它很快,因为它将源代码编译成了本地机器码(使用了JIT)

它很灵活,因为除了极少数的额外工作需要做外,它就能将JIT加入你的解释器中

它还是很灵活,因为你能使用RPython实现你的解释器,这个比其他的(比如C语言)更易扩展。事实上,它是如此的简单,这里有一篇教程教你如何实现你自己的解释器。

附录: 其他一些你可能已经听过的名字

Python 3000 (Py3k): Python 3.0的一个别名,2008年释出的一个主要版本,但是它并不向后兼容.。Py3k团队预测这个版本被完全采用可能需要5年时间.。现在绝大多数(注意:这个是江湖传闻)Python开发者继续在使用2.x版本,不过现在人们越来越多的对Py3k开始关心了。

Cython: 一个Python的超集,能够调用C语言的函数

目标: 允许你为你的Python代码写C扩展

允许你为你的Python代码加入静态类型,运行编译并达到接近C语言的性能。

这个跟PyPy比较类似,但是不是一样的。使用这个的时候,在提交给编译器之前必须用户代码里面写好这些特殊代码。如果使用PyPy的话,你写的还是普通形式的Python代码,编译器会帮你处理一切优化的工作。

Numba: 将JIT加入到被注解的Python代码中,简单来讲就是,你给它一些提示,它就会优化加速你这段代码。Numba是Anaconda发行版(一系列数据分析和管理的软件包)的一部分。

IPython: 跟我们讨论过的其他版本完全不一样。这是一个Python的计算环境。为一些GUI工具集和浏览器体验等提供支持。

Psyco: 一个Python的扩展模块,也是早先的一种Python JIT的成果。 然而,它已经被标注为“停止维护和死亡”了。事实上,Psyco的首席开发者Armin Rigo现在在为PyPy工作。

语言绑定

RubyPython: Ruby和Python虚拟机的一座桥梁。允许你在你的Ruby代码中嵌入Python代码。你定义Python的起始位置,然后RubyPython负责在不同VM直接传递整理数据。

PyObjc: Python和Objective-C语言直接的桥梁。实际上,这意味着你能在你的Python代码中使用Objective-C的库(包括创建一个OS X应用程序所需要的一切),反过来在Objective-C里面也可以使用Python的模块。这样的话,CPython用C语言来实现就很方便了,因为C语言是Objective-C的一个子集。

PyQt: 同PyObjc帮你绑定OS X GUI组件类似,PyQt帮你绑定Qt应用程序框架,让你可以创建丰富的图形界面,访问关系数据库等等。另外的一个旨在帮你简化从Python到另外的框架的工具。

JavaScript 框架

pyjs (Pyjamas): Python中一个创建web和桌面应用程序的框架。包含一个Python-to-JavaScript的编译器和其他一些工具。

Brython: 一个使用JavaScript语言写的Python虚拟机,可以让Py2k 代码在浏览器中执行。

python会实现编译功能吗_为什么会有这么多python?其实python并不是编程语言!相关推荐

  1. python语言是编译性语音_最强编程语言 Java 和最受欢迎之 Python 的巅峰对决

    作为程序员们的看家利器之编程语言,倘若技术开发者对其掌握得越深则对自身职业生涯越有益处,然随着技术的更新变革,我们在日常使用不单单只会用到一门编程语言,那么究竟该如何选择一门新的语言来上手?本文中,将 ...

  2. python可以实现vba功能吗_再见 VBA!神器工具统一 Excel 和 Python

    原标题:再见 VBA!神器工具统一 Excel 和 Python 关注 作者:东哥起飞 来源:Python数据科学 大家好,我是东哥. 经常给大家推荐好用的数据分析工具,也收到了铁子们的各种好评.这次 ...

  3. [转载] python模块的分类有哪些_整理了一份清单,常见Python问题的快速解答包

    参考链接: 使用随机数的自动井字游戏的Python实现 Python继续流行.同时,Web开发,数据科学和机器学习等领域的需求仍在不断增长,其中Python是这些领域中的通用编程语言. 随着对Pyth ...

  4. python中常用的序列化模块_第六章 常用模块(5):python常用模块(序列化模块:pickle,json,shelve,xml)...

    6.3.7 序列化模块 (pickle,json,shelve,xml) 文件写入,数据传输时,我们都是以字符串形式写入的(因为字符串可以encode成bytes). 那其他类型(比如字典,列表等)想 ...

  5. bit是python最快的bitcoin库_新的Bitcoinpython节点比以前的Python库快100倍

    3月27日,Bitcoin Cash(BCH)粉丝认识了用Python编程语言编写的新BCH完整节点. 该项目名为Bitcoinpython,是一个现代化的BCH库,其创建者声称它是速度最快的Pyth ...

  6. python如何赚外快 淘宝_业余时间怎么赚外快?用Python赚钱的5个方法!

    Python作为一门编程语言,一门技术,就一定能够为我们所用,至少赚个外快是绝对没有问题的. 渠道一:淘宝搜python程序 可以到淘宝上搜,Python程序,到相应的店里找客服,就说你想做程序开发, ...

  7. python源码编译为库_【Python笔记】如何源码编译依赖LAPACK和ATLAS库的NumPy包

    上篇笔记介绍了不依赖lapack和atlas库的NumPy包源码编译/安装方法,但"纯净版"的NumPy会损失性能,故本篇笔记说明如何源码编译安装依赖lapack和atlas库的N ...

  8. python 功能 代码_挑战“不可能”的代码:你不知道的Python功能

    本文转载自公众号"读芯术"(ID:AI_Discovery) Python看似简单,但实则变化万千,笔者总都能看到一些代码以近乎不可能的方式呈现.这些功能很精妙,以至于我无法想象没 ...

  9. python 两个数据框合并计算_一文掌握Excel、SQL、Python【数据合并】大法!

    文章最后有录制的讲解视频,如果看文章不舒服的话,可以直接滑到文末看视频,希望你能喜欢~ 在工作中,会经常遇到将多张表合并为一张表的需求:在面试的时候,有时也会被面试官问到左连接.右连接.内连接的区别. ...

  10. python是一门高级的计算机语言_为有抱负的开发者推荐的最佳 10 门编程语言

    编程是技术革新的核心,当今的编程语言有能力让开发者不再束缚他们的潜力来构建未来的技术. 如果你是一名具有前瞻性的开发者或者想成为一名具有前瞻能力的开发者,那么,是时候开始学习编程了,至少在最好的编程语 ...

最新文章

  1. 考察新人的两道c语言题目
  2. 2021最大看点AI for Science,在哪些领域有斩获?
  3. (uC/OS-II学习笔记)关于共享资源与信号量
  4. 重定向、管道和用户管理练习题
  5. 9.匿名函数:lambda表达式/filter()/map()
  6. SecureCRT密钥远程登录Linux
  7. conda配置环境变量并且激活
  8. 二、将mysql用作一个简单的计算器
  9. Linux 引导流程解析
  10. iOS 学习 - 24.全局跑马灯,支持后台回到前台
  11. 2022超级好看动态视频官网HTML源码
  12. 基于树莓派的人脸识别门禁系统
  13. FishC笔记—31 讲 永久存储:腌制一缸美味的泡菜
  14. 企业微信通讯录可以导出吗?如何导出?
  15. questasim仿真优化加速问题(object无信号,无法看波形,(vsim-12110) All optimizations are disabled,error loading design)
  16. 用html实现贪吃蛇游戏思路,贪吃蛇游戏
  17. 业绩差距拉大 11家消费金融公司座次洗牌
  18. Android仿keep运动轨迹动画,Android仿Keep运动休息倒计时圆形控件
  19. FROM_GLC的介绍与数据下载教程
  20. cdma特有效应_CDMA九问九答

热门文章

  1. jquery提交表单验证示例代码
  2. 汤唯:《在街头卖艺的那些日子》
  3. 如何实现网页中按钮的自动点击?
  4. composer require fxp/composer-asset-plugin 失败
  5. Mel中级教程精华篇预告
  6. pandas中Category的应用
  7. 计算机英语口语app,最实用五大英语口语app,强烈推荐
  8. 计算机驱动程序的安装过程,u盘驱动程序安装,教您如何安装u盘驱动程序
  9. 光栅渲染器(二)画线
  10. 在chrome的网址上搜索总是跳转到百度首页