簡體   English   中英

Cython:返回輸入的內存視圖的函數的異常類型

[英]Cython: exception type for a function returning a typed memoryview

在函數的cdef簽名中:

cdef const unsigned char[:, :] my_fn(input) except <????> :

我應該放入<????>嗎?

如果我正確理解文檔 ,則必須指定異常類型,才能使異常向上傳播到Python堆棧。

我嘗試了諸如[b'\\x00']和空Cython數組的方法,但沒有任何效果。

壞消息:你做不到。 好消息:您不必這樣做!

僅當cdef函數返回一個int ,一個enum,一個float或一個指針-基本上可以通過C中的==比較有意義的東西時,帶有except <xxx>的語法才有可能。

類型化的內存視圖是Python對象,當返回的對象為空指針時,該對象具有內置的方式來指示錯誤。 因此,您不必定義一個例外值,因為它已經被定義了!

例如:

%%cython
cdef int[:] worker(int[:] memview, int index):
    memview[index]=10 
    return memview

def runit(index):
    cdef int mem[4]
    print(worker(mem,index))

現在

runit(4)   #4 -> out of bounds
print("I still run")

不會顯示“我仍在運行”,因為會傳播越界異常。

對於不是Python對象的返回值,例如int ,則不是這種情況:

%%cython
cdef int worker(int[:] memview, int index):
    return memview[index]

現在:

runit(4)   #4 -> out of bounds
print("I still run")

打印“ 0”和“我仍在運行”,因為該錯誤不會傳播。 我們可以選擇一個例外值,例如-1以便通過return-value = -1傳播錯誤:

%%cython
cdef int worker(int[:] memview, int index) except -1:
    return memview[index]

現在,不再打印“我仍在跑步”。

但是,有時沒有很好的例外值,例如因為memview可以包含任何整數值:

%%cython
cdef int worker(int[:] memview, int index) except -1:
    return memview[index]

def runit(index):
    cdef int mem[4]
    mem[0]=-1
    print(worker(mem, index))

現在,跑步

runit(0)
print("I still run")

以虛假錯誤結束:

SystemError:返回NULL而不設置錯誤

解決方法是使用

cdef int worker(int[:] memview, int index) except *

對於runit(0)runit(4)具有正確的行為。

那么使用except *except -1相比要花費多少except -1 它們不是很高:

如果返回值是-1 (這是默認的“ exception”值),那么我們知道可能會發生錯誤(這只是確定性,不是可能性),然后通過PyErr_Occurred()檢查,是否確實如此。

正如@DavidW在評論中提到的,還可以使用except? -1 except? -1的優點是更易於閱讀和理解。 有趣的是,這將產生與except *相同的C代碼,因為默認錯誤值為-1

但是, except? -syntax允許我們選擇函數結果,而我們必須為此付出PyErr_Occurred()的開銷。 例如,如果我們知道結果-1經常出現而-2幾乎從不出現,那么我們可以使用except? -2 僅在函數結果為-2時才檢查except? -2PyErr_Occured() ,這意味着幾乎不會(在except *的情況下,它會經常被檢查-每次返回-1 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM