[英]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? -2
和PyErr_Occured()
,這意味着幾乎不會(在except *
的情況下,它會經常被檢查-每次返回-1
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.