這篇博文還是講關於提高Python運行效率的,這確實是一個值得去仔細研究一番的問題,這篇博文介紹完Cython後,接着還要介紹線程、進程和協程在提高Python代碼運行效率起着怎樣的作用,那麼我的這個系列的博文基本上寫完了。
首先要介紹一下各種*ython,太多了,什麼python,pypy呀,等等,都是什麼呢。這裏簡單的做個介紹。
CPython:這是平時用的最廣泛的,是用C語言實現的解釋器,平時說的Python一般都是指CPython。
Jython:用Java實現的的python解釋器。
IronPython:用C#實現的python解釋器。
RubyPython:用Ruby實現的Python解釋器。
Brython:用Javascript實現的Python解釋器。
PyPy:用rPython(是Python的一個子集)實現的python解釋器。
Cython: 一個Python的超集,能夠調用C語言的函數,允許你爲你的Python代碼寫C擴展,允許你爲 你 的 Python代碼加入靜態類型,運行編譯並達到接近C語言的性能。
IPython:跟其他版本完全不一樣,這是一個Python的計算環境。爲一些GUI工具集和瀏覽器體驗等提供 支 持。
Psyco:已經停止維護了,發展成爲現在的PyPy了。
PyObjc:Python和Objective-C語言直接的橋樑。這意味着能在你的Python代碼中使用Objective-C 的 庫(包括創建一個OS X應用程序所需要的一切),反過來在Objective-C裏面也可以使 用 Python的模塊。
PyQt::同PyObjc幫你綁定OS X GUI組件類似,PyQt幫你綁定Qt應用程序框架,讓你可以創建豐富的 圖 形界面,訪問關係數據庫等等。
pyjs (Pyjamas): Python中一個創建web和桌面應用程序的框架。包含一個Python-to-JavaScript的編 譯 器和其他一些工具。
Python 3000 (Py3k):Python 3.0的一個別名,2008年釋出的一個主要版本,但是它並不向後兼容。
下面開始介紹Cython吧。前兩篇博文介紹了利用Python對外接口,使用C/C++來提高運行效率(參見博文《初用C/C++擴展Python,提高性能》和《再探C/C++擴展Python》)。但是有個問題,對於對C/C++使用不是很熟練的人(比如我,雖然懂C和C++,但用的也是不是很熟練呀),用這種方法的話,費時又費力,就在這個時候Cython出現了,它可以把Python代碼直接編譯成C/C++代碼,從而獲得性能上的提升。
(1)基本安裝及使用
第一步肯定是安裝,安裝很簡單,用pip安裝,一條命令就可以搞定。
sudo pip install -U cython
如果想知道它怎麼用,打開終端,輸入cython,就會有相關命令幫助。如下圖:
看看,它的命令相關的用法都已經告訴了,在此我就不過多介紹了,英文不好的,可以用谷歌翻譯,一般都是可以理解的了的。下面隨便寫個python代碼試用一下。代碼如下:
#coding=utf-8 def is_primenumber(n): if n <= 1: return False if n == 2: return True if n == 3: return False for i in xrange(2,n//2 + 1): if n % i == 0: return True return False
還是判讀一個正整數是不是素數,文件名爲good.py。根據上圖中cython命令使用方法,打開終端,切換到文件所在目錄,執行如下命令
cython good.py
然後就在當前目錄生成一個名爲good.c的文件,當然你也可以自己指定路徑及文件名。根據上圖的命令使用方法提示,我們可以用參數o。如下:
cython good.py -o /home/liuonghua/good1.c
那麼會將good.py編譯成爲等價的c/c++代碼會拷貝到/home/liulong/目錄下的good1.c文件下(如果該文件不存在會自動創建)。我們可以打開這個good.c文件看看,3000多行呀,一個只有十五六行的Python代碼被編譯成了3000多行的C/C++代碼。那怎麼在這3000多行代碼中找到對應的用Python代碼寫的代碼呀?在文件裏搜索“is_primenumber”,可以找的到,由於代碼比較長,在此不貼了,至於cython將python代碼編譯成c/c++代碼的機理是什麼,有時間研究一番後再和大家分享我的學習經驗。
竟然以及被編譯成立.c文件,那麼接下來的操作和上篇博文《初用C/C++擴展Python,提高性能》一樣,將它編譯成.so文件(怎麼編譯,可參考上篇博文),然後拷貝到python2.7/dist-packages目錄下,然後就可以利用該模塊了。在此不過多闡述,直接貼上我的測試運行效率的結果結果。
代碼如下:
#coding=utf-8 from good import is_primenumber import datetime def is_prime(n): if n <= 1: return False if n == 2: return True if n == 3: return False for i in xrange(2,n//2 + 1): if n % i == 0: return True return False t0 = datetime.datetime.now() a = is_prime(10) t1 = datetime.datetime.now() b = is_primenumber(10) t2 = datetime.datetime.now() print t2-t1,t1-t0
結果如下:
性能是不是提高了很多。不過每次都要編譯未免太麻煩,還好Cython提供了一個無需顯示編譯的方案:pyximport。只要將原有的Python代碼的後綴從.py改爲.pyx即可。
改完之後打開終端,輸入命令:
>>>python
>>>import good
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named good
>>>import pyximport;pyximport.install()
(None,<pyximport.pyximport.PyxImporter object at 0x10fbd05d0>)
>>>import good
>>>import good.__file__
'/home/liulonghua/test/build/lib.linux-x86_64-2.7/good.so'
這一部分,上週日時我在自己的電腦上操作不成功,所用系統是Ubuntu 16.04 LTS,但是週一的時候在公司的電腦上操作成功了,公司電腦系統Ubuntu 14.04 LTS,不知道爲什麼,可能是Cython還不能完全支持Ubuntu 16.04 吧,有興趣的可以去研究下。