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代碼:
|
你可能會說,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