在函数的cdef
签名中:
cdef const unsigned char[:, :] my_fn(input) except <????> :
我应该将<????>
放入什么?
如果我正确理解documentation,则指定异常类型是异常传播Python堆栈所必需的。
我尝试了[b'\x00']
并且空的Cython数组,没有效果。
答案 0 :(得分:3)
坏消息:你不能这样做。好消息:你不必这样做!
只有当except <xxx>
函数返回cdef
,枚举,浮点数或指针时,int
的语法才有可能 - 基本上通过{比较有意义的事情C中的{1}}
类型化内存视图是一个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))
没有打印&#34;我仍在运行&#34;因为传播了越界异常。
对于不是Python对象的返回值,情况不是这样,例如runit(4) #4 -> out of bounds
print("I still run")
:
int
现在:
%%cython
cdef int worker(int[:] memview, int index):
return memview[index]
打印&#34; 0&#34;和#34;我仍然运行&#34;,因为错误没有传播。我们可以选择一个例外值,例如runit(4) #4 -> out of bounds
print("I still run")
,以便通过return-value = -1传播错误:
-1
现在,&#34;我仍然跑步&#34;不再打印。
但是,有时候没有好的例外值,例如因为%%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))
以虚假错误结束:
SystemError:返回NULL而不设置错误
解决方案是使用
runit(0)
print("I still run")
具有cdef int worker(int[:] memview, int index) except *
和runit(0)
的正确行为。
与runit(4)
相比,使用except *
的成本是多少?它们并不高:
如果返回的值是except -1
(这是默认值&#34;例外&#34;值),那么我们就知道可能发生错误(这可能不是确定的)并且检查通过-1
,是否真的如此。
正如@DavidW在评论中提到的那样,也可以使用PyErr_Occurred()
,其优点是更易于阅读和理解。有趣的是,这会产生与except? -1
相同的C代码,因为默认的错误值是except *
!
但是,-1
- 语法允许我们选择我们必须支付except?
开销的函数结果。例如,如果我们知道结果PyErr_Occurred()
经常发生且-1
几乎从未发生过,那么我们可以使用-2
并仅在结果时检查except? -2
该函数的函数是PyErr_Occured()
,这意味着几乎从不(在-2
的情况下,它会经常被检查 - 每次都返回except *
。)