Exception handling Cython:返回类型化memoryview的函数的异常类型
在函数的Exception handling Cython:返回类型化memoryview的函数的异常类型,exception-handling,cython,typed-memory-views,Exception Handling,Cython,Typed Memory Views,在函数的cdef签名中: cdef const unsigned char[:, :] my_fn(input) except <????> : cdef const unsigned char[:,:]my_fn(输入)除了: 我应该在中输入什么 如果我理解正确,指定异常类型是异常向上传播到Python堆栈所必需的 我尝试了[b'\x00']和空的Cython数组,但都不起作用 坏消息:你做不到。好消息:你不必这么做 只有当cdef函数返回一个int、一个枚举、一个浮点或一个指
cdef
签名中:
cdef const unsigned char[:, :] my_fn(input) except <????> :
cdef const unsigned char[:,:]my_fn(输入)除了:
我应该在
中输入什么
如果我理解正确,指定异常类型是异常向上传播到Python堆栈所必需的
我尝试了
[b'\x00']
和空的Cython数组,但都不起作用 坏消息:你做不到。好消息:你不必这么做
只有当cdef
函数返回一个int
、一个枚举、一个浮点或一个指针时,才可能使用except
语法-基本上,在C中通过=
进行比较是有意义的
类型化内存视图是一个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
,以便通过返回值=-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-1
相比,使用except*
的成本是多少呢?它们并不是很高:
如果返回值为-1
(这是默认的“异常”值),则我们知道可能发生了错误(这只是一种可能性而不是确定性),并通过PyErr_occurrent()
检查是否真的发生了错误
正如@DavidW在评论中提到的,也可以使用except-1
的优点是易于阅读和理解。有趣的是,这将产生与相同的C代码,除了*
,因为默认错误值是-1
但是,
except?
-语法允许我们选择函数结果,我们必须为此支付PyErr\u occurrent()
的开销。例如,如果我们知道结果-1
经常出现,而-2
几乎从不出现,那么我们可以使用除了-只有当函数的结果是-2
时,才会检查2
和PyErr\u occurrend()
,这意味着几乎永远不会检查(在除外*
的情况下,会经常检查-每次返回-1
)或除外-1
表示-1可能是错误(但不是必需的)@DavidW谢谢你的提示!我已经相应地更新了我的答案。另一种方法是通过引用传入现在的返回值,而不是返回一个表示错误代码的int。