在cdef
函数的签名中:
cdef const unsigned char[:, :] my_fn(input) except <????> :
我要放<????>
什么?
如果我正确理解了文档,那么指定异常类型对于将异常传播到 Python 堆栈是必要的。
我尝试了一些[b'\x00']
空的 Cython 数组,但没有任何效果。
在cdef
函数的签名中:
cdef const unsigned char[:, :] my_fn(input) except <????> :
我要放<????>
什么?
如果我正确理解了文档,那么指定异常类型对于将异常传播到 Python 堆栈是必要的。
我尝试了一些[b'\x00']
空的 Cython 数组,但没有任何效果。
坏消息:你做不到。好消息:您不必这样做!
仅当函数返回一个、一个枚举、一个浮点数或一个指针except <xxx>
时才可能使用 with 的语法- 基本上是在 C中比较有意义的东西。cdef
int
==
类型化的内存视图是一个 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
多少?它们并不高:
如果返回值是-1
(这是默认的“异常”值),那么我们知道可能发生了错误(这只是一种可能性而不是确定性)并检查 via PyErr_Occurred()
,是否真的如此。
正如评论中提到的@DavidW,也可以使用except? -1
它具有更易于阅读和理解的优点。有趣的是,这会产生与 相同的 C 代码except *
,因为默认的错误值是-1
!
但是,except?
- 语法允许我们选择我们必须为其支付开销的函数结果PyErr_Occurred()
。例如,如果我们知道结果-1
经常发生而且-2
几乎从不发生,那么我们可以使用except? -2
andPyErr_Occured()
仅在函数的结果为 时才被检查-2
,这意味着几乎从不(在这种情况下except *
会经常检查- 每次-1
都返回)。