
Cython 估計很多人都聽說過,它是用來對 Python 進行加速的。如果你在使用 Python 編程時,有過如下想法,那麼 Cython 非常適合你。1)因為某些需求導致不得不編寫一些多重嵌套的循環,而這些循環如果用 C 語言來實現會快上百倍,但是不熟悉 C 或者不知道 Python 如何與 C 進行交互;2)因為 Python 解釋器的性能原因,如果將 CPython 解釋器換成 PyPy,或者乾脆換一門語言,比如 Rust,將會得到明顯的性能提升,可是換不得。因為你的項目組規定只能使用 Python 語言,解釋器只能是 CPython;3)Python 是一門動態語言,但你希望至少在數字計算方面,能夠加入可選的靜態類型,這樣可以極大地加速運算效果。因為單純的數字相加不太需要所謂的動態性,尤其是當你的程序中出現了大量的計算邏輯時;4)對於一些計算密集型的部分,你希望能夠寫出一些媲美 Numpy, Scipy, Pandas 的算法;5)你有一些已經用 C、C++ 實現的庫,你想直接在 Python 內部更好地調用它們,並且不使用 ctypes、cffi 等模塊;6)也許你聽說過 Python 和 C 可以無縫結合,通過 C 來為 Python 編寫擴展模塊,將 Python 代碼中性能關鍵的部分使用 C 進行重寫,來達到提升性能的效果。但是這需要你對 Python 解釋器有很深的了解,熟悉底層的 Python/C API,而這是一件非常痛苦的事情;如果你有過上面的一些想法,那麼證明你的 Python 水平是很優秀的,然而這些問題總歸是要解決的,於是 Cython 便閃亮登場了。注意:Cython 並不是一個什麼實驗性的項目,它出現的時間已經不短了,並且在生產環境中久經考驗,我們完全是有理由學習它的。下面讓我們開始 Cython 的學習之旅吧,悄悄說一句,我個人非常喜歡 Cython 的語法。1)Cython 是一門編程語言,它將 C 和 C++ 的靜態類型系統融合在了 Python 身上。Cython 源文件的後綴是 .pyx,它是 Python 的一個超集,語法是 Python 語法和 C 語法的混血。當然我們說它是 Python 的一個超集,因此你寫純 Python 代碼也是可以的。2)當我們編寫完 Cython 代碼時,需要先將 Cython 代碼翻譯成高效的 C 代碼,然後再將 C 代碼編譯成 Python 的擴展模塊。在早期,編寫 Python 擴展都是拿 C 去寫,但是這對開發者有兩個硬性要求:一個是熟悉 C,另一個是要熟悉解釋器提供的 C API,這對開發者是一個非常大的挑戰。此外,拿 C 編寫代碼,開發效率也非常低。而 Cython 的出現則解決了這一點,Cython 和 Python 的語法非常相似,我們只需要編寫 Cython 代碼,然後再由 Cython 編譯器將 Cython 代碼翻譯成 C 代碼即可。所以從這個角度上說,拿 C 寫擴展和拿 Cython 寫擴展是等價的。至於如何將 Cython 代碼翻譯成 C 代碼,則依賴於相應的編譯器,這個編譯器本質上就是 Python 的一個第三方模塊。它就相當於是一個翻譯官,既然用 C 寫擴展是一件痛苦的事情,那就拿 Cython 去寫,寫完了再幫你翻譯成 C。因此 Cython 的強大之處就在於它將 Python 和 C 結合了起來,可以讓你像寫 Python 代碼一樣的同時還可以獲得 C 的高效率。所以我們看到 Cython 相當於是高級語言 Python 和低級語言 C 之間的一個融合,因此有人也稱 Cython 是 "克里奧爾編程語言"(creole programming language)。克里奧爾人是居住在西印度群島的歐洲人和非洲人的混血兒,以此來形容 Cython 也類似於是一個(Python 和 C 的)混血兒。Python 和 C 語言大相徑庭,為什麼要將它們融合在一起呢?答案是:因為這兩者並不是對立的,而是互補的。Python 是高階語言、動態、易於學習,並且靈活。但這些優秀的特性是需要付出代價的,因為 Python 的動態性、以及它是解釋型語言,導致其運行效率比靜態編譯型語言慢了好幾個數量級。而 C 語言是最古老的靜態編譯型語言之一,並且至今也被廣泛使用。從時間來算的話,其編譯器已有將近半個世紀的歷史,在性能上做了足夠的優化,因此 C 語言是非常低級、同時又非常強大的。然而不同於 Python 的是,C 語言沒有提供保護措施(沒有 GC、容易內存泄露),以及使用起來很不方便。所以兩個語言都是主流語言,只是特性不同使得它們被應用在了不同的領域。而 Cython 的美麗之處就在於:它將 Python 語言豐富的表達能力、動態機制和 C 語言的高性能匯聚在了一起,並且代碼寫起來仍然像寫 Python 一樣。注意:除了極少數的例外,Python 代碼(2.x和3.x版本)已經是有效的 Cython 代碼,因為 Cython 可以看成是 Python 的超集。並且 Cython 在 Python 語言的基礎上添加了一些少量的關鍵字來更好地開發 C 的類型系統,從而允許 Cython 編譯器生成高效的 C 代碼。如果你已經知道 Python 並且對 C 或 C++ 有一定的基礎了解,那麼你可以直接學習 Cython,無需再學習其它的接口語言。另外,我們其實可以將 Cython 當成兩個身份來看待:1)如果將 Cython 翻譯成 C,那麼可以看成 Cython 的 '陰';2)如果將 Python 作為膠水連接 C 或者 C++,那麼可以看成是 Cython 的 '陽'。我們可以從需要高性能的 Python 代碼開始,也可以從需要一個優化 Python 接口的 C、C++ 開始,而我們這裡是為了學習 Cython,因此顯然是選擇前者。為了加速 Python 代碼,Cython 將使用可選的靜態類型聲明並通過算法來實現大量的性能提升,尤其是靜態類型系統,這是實現高性能的關鍵。關於 Cython,最讓人困惑的就是它和 CPython 之間的關係,但是需要強調的是這兩者是完全不同的。首先 Python 是一門語言,它有自己的語法規則,我們按照 Python 語言規定的語法規則編寫的代碼就是 Python 源代碼。但是源代碼只是一個或多個普通的文本文件,我們需要使用 Python 語言對應的解釋器來執行它。而 Python 解釋器也會按照同樣的語法規則來對我們編寫的 Python 源代碼進行分詞、語法解析等等,如果我們編寫的代碼不符合 Python 的語法規則,那麼會報出語法錯誤,也就是 SyntaxError。如果符合語法規範的話,那麼會順利地生成抽象語法樹(Abstract Syntax Tree,簡稱 AST),然後將 AST 編譯成指令集合,也就是所謂的字節碼(bytes code),最後再執行字節碼。所以 Python 源代碼是需要 Python 解釋器來操作的,如果我們想做一些事情的話,光寫成源代碼是不行的,必須要由 Python 解釋器將我們的代碼解釋成機器可以識別的指令進行執行才可以。而 CPython 正是 Python 語言對應的解釋器,並且它也是官方實現的標準解釋器,同時還是使用最廣泛的一種解釋器。基本上我們使用的解釋器都是 CPython,也就是從官網下載、然後安裝之後所得到的。標準解釋器 CPython 是由 C 語言實現的,除了 CPython 之外還有 Jython(java實現的 Python 解釋器)、PyPy(Python 語言實現的 Python 解釋器)等等。總之設計出一門語言,還要有相應的解釋器才可以;至於編譯型語言,則是對應的編譯器。最後重點來了,我們說 CPython 解釋器是由 C 實現的,它給 Python 語言提供了 C 級別的接口,也就是熟知的 Python/C API。比如:Python 的列表,底層對應的是 PyListObject;字典則對應 PyDictObject,等等等等。所以當我們在 Python 中創建一個列表,那麼 CPython 在執行的時候,就會在底層創建一個 PyListObject。因為 CPython 是用 C 來實現的,最終肯定是將 Python 代碼翻譯成 C 級別的代碼,然後再變成機器碼交給 CPU 執行。而 Cython 也是如此,Cython 代碼也要被翻譯成 C 代碼,然後 C 代碼再變成擴展(本質上也是機器碼),導入之後直接執行,而無需動態解釋。因此 Cython 是一門語言,它並不是Python 解釋器的另一種實現,它的地位和 CPython 不是等價的,不過和 Python 是平級的。總結:Cython 是一門語言,可以通過 Cython 源代碼生成高效的 C 代碼,再將 C 代碼編譯成擴展模塊,同樣需要 CPython 來進行調用。以上我們就解釋了什麼是 Cython,以及為什麼需要 Cython。下一篇文章我們來比較一下,Cython, Python, C 擴展, 還有原生的 C 語言之間的效率差異。




鑽石舞台 發表在 痞客邦 留言(0) 人氣()