一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Cython應(yīng)用手記

 londonKu 2012-09-05
作者: 日期:
gashero
2010-03-29

目錄

  • 1   簡(jiǎn)介
  • 2   基本使用
  • 3   調(diào)用其他C庫(kù)
    • 3.1   簡(jiǎn)單例子
    • 3.2   重新定義外部C庫(kù)的定義
  • 4   類定義
  • 5   與Python交互

1   簡(jiǎn) 介

一種為Python寫C擴(kuò)展的方式,嘗試一下。

參考文獻(xiàn):

  1. [r] 官方主頁(yè): http://www./
  2. [r] Cython三分鐘入門: http://blog.csdn.net/lanphaday/archive/2009/09/17/4561611.aspx
  3. [u] A quick Cython introduction: http://www./wordpress/?p=116 其實(shí)就是上文的原文
  4. [i] Cython's Documentation: http://docs./ 看到"Extensioin types"

2   基 本使用

Cython基于pyrex,但是擁有更多功能和優(yōu)化。用來(lái)寫Python的C擴(kuò)展的,并生成有效的C代碼。寫出的文件擴(kuò)展名是 ".pyx" ,已經(jīng)可以算作一種語(yǔ)言了。

一個(gè)簡(jiǎn)單的加法函數(shù)( addtest.pyx ):

def addtest(a,b):
    cdef float c=a+b
    return c

編譯和生成動(dòng)態(tài)庫(kù):

cython addtest.pyx
gcc -c -fPIC -I/usr/include/python2.5 addtest.c
gcc -shared addtest.o -o addtest.so

使用:

$ python
>>> import addtest
>>> addtest(1,2)
3.0

構(gòu)建Cython代碼的方式:

  1. 使用 setup.py ,常用
  2. 使用pyximport導(dǎo)入 ".pyx" 文件
  3. 運(yùn)行cython命令編譯出.c文件后再編譯成.so文件
  4. 使用Sage

使用 setup.py 方式,例如一個(gè) hello.pyx 文件,編寫的 setup.py 如下:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules=[Extension('hello',['hello.pyx'])]

setup(
    name='Hello world app',
    cmdclass={'build_ext':build_ext},
    ext_modules=ext_modules
)

構(gòu)建使用命令 python setup.py build_ext --inplace 。

Cython提高速度的主要原因是使用靜態(tài)類型??梢栽谌魏螀?shù)前直接使用C的類型定義。函數(shù)內(nèi)的話要加"cdef"前綴。如:

def f(double x):
    cdef double ret
    ret=x**2-x
    return ret

僅僅使用Cython編譯純Python代碼可以提高35%的性能,幾乎全部使用靜態(tài)類型以后提高4倍。

C風(fēng)格函數(shù)聲明,"except? -2"表示返回-2時(shí)就是出錯(cuò)了。不過(guò)"except *"是肯定安全的。如:

cdef double f(double) except? -2:
    return x**2-x

使用cpdef時(shí),這個(gè)函數(shù)就可以同時(shí)被C和Python調(diào)用了。當(dāng)使用了C函數(shù)時(shí),因?yàn)楸荛_(kāi)了昂貴的函數(shù)調(diào)用,旺旺可以提高150倍的速度。

不要過(guò)度優(yōu)化,一步步的優(yōu)化并且查看profile。使用"cython -a"參數(shù)可以查看HTML報(bào)告。

3   調(diào) 用其他C庫(kù)

3.1   簡(jiǎn) 單例子

導(dǎo)入"math.h"中的 sin() 函數(shù)并使用:

cdef extern from "math.h":
    double sin(double)

cdef double f(double x):
    return sin(x*x)

Cython不會(huì)去掃描頭文件,所以自己必須再聲明一遍。下面是使用時(shí)必須連接上其他庫(kù)的 setup.py 文件:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules=[
    Extension('demo',['demo.pyx',],libraries=['m',])
    ]

setup(
    name='Demos',
    cmdclass={'build_ext':build_ext},
    ext_modules=ext_modules,
)

同理可以使用任何動(dòng)態(tài)或靜態(tài)編譯的庫(kù)。

3.2   重 新定義外部C庫(kù)的定義

一段C代碼,頭文件中的類型定義與函數(shù)聲明:

typedef struct _Queue Queue;
typedef void *QueueValue;

Queue *queue_new(void);
void queue_free(Queue *queue);

int queue_push_head(Queue *queue, QueueValue data);
QueueValue queue_pop_head(Queue *queue);
QueueValue queue_peek_head(Queue *queue);

int queue_push_tail(Queue *queue, QueueValue data);
QueueValue queue_pop_tail(Queue *queue);
QueueValue queue_peek_tail(Queue *queue);

int queue_is_empty(Queue *queue);

對(duì)應(yīng)的Cython定義,寫入一個(gè)".pxd"文件中:

cdef extern from "libcalg/queue.h":
    ctypedef struct Queue:
        pass
    ctypedef void* QueueValue

    Queue* new_queue()
    void queue_free(Queue* queue)

    int queue_push_head(Queue* queue, QueueValue data)
    QueueValue  queue_pop_head(Queue* queue)
    QueueValue queue_peek_head(Queue* queue)

    int queue_push_tail(Queue* queue, QueueValue data)
    QueueValue queue_pop_tail(Queue* queue)
    QueueValue queue_peek_tail(Queue* queue)

    bint queue_is_empty(Queue* queue)

大部分時(shí)候這種聲明與頭文件幾乎是一樣的,你可以直接拷貝過(guò)來(lái)。唯一的區(qū)別在最后一行,C函數(shù)的返回值其實(shí)是布爾值,所以用bint類型會(huì)轉(zhuǎn)換成 Python的布爾值。

這里可以不關(guān)心結(jié)構(gòu)體的內(nèi)容,而只是用它的名字。

4   類 定義

一個(gè)類的例子:

cimport cqueue
cimport python_exc

cdef class Queue:
    cdef cqueue.Queue_c_queue
    def __cinit__(self):
        self._c_queue=cqueue.new_queue()

這里的構(gòu)造函數(shù)是 __cinit__() 而不是 __init__() 。雖然 __init__() 依然有效,但是并不確保一定會(huì)運(yùn)行(比如子類忘了調(diào)用基類的構(gòu)造函數(shù))。因?yàn)槲闯跏蓟闹羔樈?jīng)常導(dǎo)致Python掛掉而沒(méi)有任何提示,所以 __cinit__() 總是會(huì)在初始化時(shí)調(diào)用。不過(guò)其被調(diào)用時(shí),對(duì)象尚未構(gòu)造完成,所以除了cdef字段以外,避免其他操作。如果要給 __cinit__() 構(gòu)造和函數(shù)加參數(shù),必須與 __init__() 的匹配。

構(gòu)造函數(shù)初始化資源時(shí)記得看看返回的資源是否是有效的。如果無(wú)效可以拋出錯(cuò)誤。Cython提供了內(nèi)存不足異常,如下:

def __cinit__(self):
    self._c_queue=cqueue.new_queue()
    if self._c_queue is NULL:
        python_exc.PyErr_NoMemory()

Cython提供的析構(gòu)函數(shù),僅在建立成功內(nèi)部對(duì)象時(shí)釋放內(nèi)部對(duì)象:

def __dealloc__(self):
    if self._c_queue is not NULL:
        cqueue.queue_free(self._c_queue)

將數(shù)據(jù)以通用指針?lè)绞竭M(jìn)入,和返回時(shí)的強(qiáng)制類型轉(zhuǎn)換:

cdef append(self,int value):
    cqueue.queue_push_tail(self._c_queue,<void*>value)

cdef int pop(self):
    return <int>cqueue.queue_pop_head(self._c_queue)

Cython除了支持普通Python類以外,還支持?jǐn)U展類型,使用"cdef class"定義。在內(nèi)存占用和效率上更好。因?yàn)槭褂肅結(jié)構(gòu)體存儲(chǔ)字段和方法,而不是Python字典。所以可以存儲(chǔ)任意C字段類型,而不是其 Python包裝。訪問(wèn)時(shí)也是直接訪問(wèn)C的值,而不是通過(guò)字典查找。

普通的Python類可以繼承自cdef類,但是反之則不行。Cython需要知道完整的繼承層次來(lái)定義C結(jié)構(gòu)體,并且嚴(yán)格限制單繼承。不過(guò)普通 Python類可以繼承任一數(shù)量的Python類和擴(kuò)展類型,無(wú)論在Python中還是在Cython代碼中。

5   與 Python交互

如果Cython調(diào)用Python函數(shù)失敗,則直接返回NULL,而不是異常對(duì)象。

如果一個(gè)函數(shù)既有可能返回NULL,也有可能返回0,則處理起來(lái)就比較麻煩。Python C API的做法是 PyErr_Occurred() 函數(shù)。不過(guò)這種方式有性能損耗。在Cython中你可以自己指定哪個(gè)返回值代表錯(cuò)誤,所以環(huán)境只要檢查這個(gè)返回值即可。其他所有值都回?zé)o損耗的被接受。

在函數(shù)定義時(shí)指定except子句,則僅在函數(shù)返回該值時(shí)檢查是否需要拋出異常。這樣同一個(gè)函數(shù)返回0和返回0同時(shí)返回錯(cuò)誤就可以區(qū)分開(kāi)。例子:

cdef int pop(self) except? 0:
    #...

類中的 cdef 定義C方法,而 cpdef 可以同時(shí)定義C方法和Python方法。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    国产日韩欧美一区二区| 在线日韩欧美国产自拍| 日本欧美视频在线观看免费| 91亚洲人人在字幕国产| 国产成人国产精品国产三级| 国产黄色高清内射熟女视频| 在线观看欧美视频一区| 麻豆亚州无矿码专区视频| 久久国产精品热爱视频| 人人妻人人澡人人夜夜| 国产精品流白浆无遮挡| 好吊妞视频只有这里有精品| 欧美性高清一区二区三区视频 | 经典欧美熟女激情综合网| 日本不卡在线一区二区三区| 国产日韩欧美一区二区| 麻豆亚州无矿码专区视频| 日韩精品人妻少妇一区二区| 深夜少妇一区二区三区| 久久老熟女一区二区三区福利| 亚洲精品成人午夜久久| 在线观看免费午夜福利| 人人爽夜夜爽夜夜爽精品视频| 白白操白白在线免费观看| 一级片黄色一区二区三区| 午夜精品一区免费视频| 国产成人国产精品国产三级 | 草草视频精品在线观看| 亚洲一二三四区免费视频| 99久只有精品免费视频播放| 一区二区三区日韩在线| 熟女乱一区二区三区丝袜| 国产传媒免费观看视频| 午夜资源在线观看免费高清| 国产三级黄片在线免费看| 日本少妇中文字幕不卡视频| 欧美一级特黄大片做受大屁股| 国产综合欧美日韩在线精品| 成人精品一区二区三区综合| 日本午夜免费观看视频| 中日韩免费一区二区三区|