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)的区别是很重要的,最好的办法或许是看看例子:
简而言之:机器码快的多,但字节码更易迁移,也更安全。 |
机器码随机器的变化而变化,但字节码在所有的机器上都是一样的。有人可能会认为机器码是对特定环境优化了的。
字节码随后在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类。(题外话,若你没有认真思考,这一段会很难。此时我们已经在讨论把不同语言的代码混在一起,并编译成同一程序。(Rostin 提出混合Fortran和C代码编程已经有一段时间了。所以,这并不新鲜,但仍然很酷。)) 下面是一个例子,一段合法的Jython代码:
IronPython是另一很流行的Python 实现,完全用C#实现,针对.NET平台。她运行在可以叫做.NET虚拟机的平台上,这是微软的 Common Language Runtime (CLR),同JVM相对应。 |
你可能会说,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 UnderstandPyPy具有巨大的潜力,在这一点上,它与CPython高度兼容所以它能运行Flask,Django等等)。 但关于PyPy有许多困惑 (例如,荒谬的建议创造一种PyPyPy…语言). 按我的观点,那主要是因为PyPy实际上是两种东西: 一种用RPython (非Python (我之前撒谎了))编写的Python解释器。 RPython是Python的子集,具有静态类型。在Python里,最难严格推论类型 (为什么这么困难,考虑下下面的事实:
只为清晰,我将引用这些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本事是相当棒的。它使用了一种叫做跟踪的技术,按照下面的步骤执行:
想获取更多信息,可以参考这篇文章,易于理解,并且非常有趣 最后收尾:我们使用PyPy的RPython-to-C(或者其他目标平台)编译器去编译PyPy的基于RPython实现的解释器。 |
结尾为什么它如此的伟大?为什么这个疯狂的想法值得我们去追求?我想Alex Gaynor已经在他的博客上面做了很好的解释了:“[PyPy就是未来] 因为[它]提供了更快的速度,更大的灵活性,并且对于Python的成长也提供了一个更好的平台” 总之:
|
附录: 其他一些你可能已经听过的名字
|
其它翻译版本(1) |
语言绑定
JavaScript 框架
|
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
出处:http://www.oschina.net/translate/why-are-there-so-many-pythons
为什么有这么多 Python版本的更多相关文章
-
提取bmp图片的颜色信息,可直接framebuffer显示(c版本与python版本)
稍微了解了下linux的framebuffer,这是一种很简单的显示接口,直接写入像素信息即可 配置好的内核,会有/dev/fbn 的接口,于是想能否提前生成一个文件,比如logo.fb,里面仅包含像 ...
-
Centos7下安装python,查看python版本
安装Centos的时候,一般会自带默认安装python2.x 一般用python -V可以查看python版本. 我当时安装的时候,运行了那个语句,但是却显示了一大堆出来,虽然里面也带有版本信息,但是 ...
-
LInux升级Python版本2.7.11所遇问题汇总
首先请原谅我使用校园网络,基本上打不开谷歌,网络搜取得帮助均来自度娘. 对于我这个linux新手 IT 新手来说,自己升级点东西好担心,万一出错,可能都要重来.... 参照度娘内容和自己摸索,今天晚上 ...
-
Sublime Text 2 增加python版本
当系统中装有多个python版本时,Sublime Text 2 使用哪个版本需要手动添加 键入一下内容,path输入python的安转路径 保存至Python27.sublime-build文件 ...
-
linux 多个python版本的切换
源码安装新的python版本,我的安装路径: /usr/self/Python3.5.2 修改软链接到你所安装的python版本中: 默认python命令是在/usr/bin/目录下 1 sudo m ...
-
liunx CentOS 升级Python版本
CentOS python版本是V2.6.6,升级3.4.3. 1.下载 安装包:wget http://www.python.org/ftp/python/3.4.3/Python-3.4.3.tg ...
-
Linux安装多个Python版本
服务器上的Python版本太老了,需要安装一个新的Python版本,才能跑我的代码.因为环境的需要,但是又不能卸载老的版本,所以安装一个新的,使用软链来进行升级. 使用系统自带的yum,apt-get ...
-
CentOS下更新python版本
执行#Python或#python -V或#python --version,看到版本号是2.7.5,到官网https://www.python.org/ftp/python/查看了下最新版本都到了2 ...
-
Debian中如何切换默认Python版本
当你安装 Debian Linux 时,安装过程有可能同时为你提供多个可用的 Python 版本,因此系统中会存在多个 Python 的可执行二进制文件,你可以按照以下方法使用 ls 命令来查看你的系 ...
-
自动化运维工具ansible-如何设置客户端多python版本问题
问题:在使用ansible进行管理客户主机时,发现客户主机安装了多个版本的python,并且默认版本为3.0 shell>>cat list 192.168.2.9 shell>&g ...
随机推荐
-
Intellij IDEA 初级学习文章
Intellij IDEA同时打开多个项目 IntelliJ IDEA 14.x 创建工作空间与多个Java Web项目 使用IntelliJ IDEA 14和Maven创建java web项目
-
maven 的 scope的含义
依赖范围控制哪些依赖在哪些classpath 中可用,哪些依赖包含在一个应用中.让我们详细看一下每一种范围: compile (编译范围) compile是默认的范围:如果没有提供一个范围,那该依赖的 ...
-
dll文件是什么
dll实际上是动态链接库的缩写,从windows1.0开始,动态链接库就是整个操作系统的基础,那么这有什么作用呢?在dos时代,程序员是通过编写程序来达到预期的目的的,每实现一个目的就需要编写一个程序 ...
-
Linux cat命令的使用
cat命令主要用来查看文件内容,创建文件,文件合并,追加文件内容等功能. A:查看文件内容主要用法: 1.cat f1.txt,查看f1.txt文件的内容. 2.cat -n f1.txt,查看f ...
-
时间日期Date类型
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
-
atitit.报告最佳实践oae 和报告引擎的选择
atitit.报告最佳实践oae 与报表引擎选型 1. 报表的基本的功能and结构 2 1.1. 查询设计器(配置化,metadata in html) ,anno 2 1.2. 查询引擎 2 1.3 ...
-
gulp学习笔记(一)
gulp 是基于 Nodejs 的自动任务运行器,能自动化地完成javascript/coffee/sass/less/html/image/css等文件的的测试.检查.合并.压缩.格式化.浏览器自动 ...
-
Python学习之路-Day2-Python基础3
Python学习之路第三天 学习内容: 1.文件操作 2.字符转编码操作 3.函数介绍 4.递归 5.函数式编程 1.文件操作 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个 ...
-
[转]pymongo常用操作函数
pymongo 是 mongodb 的 python Driver Editor.记录下学习过程中感觉以后会常用多一些部分,以做参考. 1. 连接数据库 要使用pymongo最先应该做的事就是先连上运 ...
-
06: dorpzone上传下载
1.1 dropzone上传下载使用 参考博客:https://www.cnblogs.com/fu-yong/p/9053515.html 1.使用dropzone需要引入文件 <link r ...