初用Cython編寫擴展模塊

    這篇博文還是講關於提高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,就會有相關命令幫助。如下圖:

wKiom1gDPFXx0WJ9AAHtoxCVqhA281.png-wh_50


看看,它的命令相關的用法都已經告訴了,在此我就不過多介紹了,英文不好的,可以用谷歌翻譯,一般都是可以理解的了的。下面隨便寫個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

結果如下:

wKioL1gDToHwof6_AAAbXxdbgAI590.png-wh_50


性能是不是提高了很多。不過每次都要編譯未免太麻煩,還好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 吧,有興趣的可以去研究下。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章