Cython:返回类型化内存视图的函数的异常类型

时间:2018-06-04 16:27:10

标签: exception-handling cython typed-memory-views

在函数的cdef签名中:

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

我应该将<????>放入什么?

如果我正确理解documentation,则指定异常类型是异常传播Python堆栈所必需的。

我尝试了[b'\x00']并且空的Cython数组,没有效果。

1 个答案:

答案 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 *。)