python - 返回多个值的 cdef 函数的 Cython 异常传播

标签 python exception cython cythonize

我有一个 cdef 函数返回一个 (int, int) 元组。我需要传播异常,因此必须为异常指定返回类型。由于我的函数从不返回负值,这可能例如是 (-1, -1)。使用 documentation 中指定的标准语法,我的函数看起来像

cdef (int, int) myFunction(int arg) except (-1, -1):
    ...

然而,当对上述函数进行cythonizing时,我得到了错误

Not allowed in a constant expression

我知道我可以在每次函数调用后打开查找异常

cdef (int, int) myFunction(int arg) except *:
    ...

但这对我来说似乎效率低下。

如何传播具有多个返回值的函数的异常?

最佳答案

答案是:你不能,至少不能使用当前版本的 Cython 的 cdef-tuples。

潜在的问题是,对于这样的元组,运算符 == 不是由 Cython 定义的(这显然可以通过比较每个条目来完成 - 但在当前版本中它没有定义)。

对于一个简单的 cdef int myfun() except * 实际上并不是一个很大的性能影响:

  • 如果结果不是-1,则几乎没有开销(仅与-1 进行比较)。
  • 如果结果是 -1PyErr_Occurred 用于检查错误,这可能意味着相当大的开销(以上都是 nogil block )
  • 可以通过except?选择一个临界值X? X,从而最小化/优化必要的 PyErr_Occured 调用次数。

但是,如果 Cython 不知道类型的 == 运算符(与 Cython 的 c 元组一样),我们基本上处于 cdef void myfun() except *情况下,这意味着没有捷径,必须始终检查/调用 PyErr_Occured


您可能会说 == 是为 Cython 的元组定义的,因为它是经过编译的。但是如果您查看生成的代码,您会发现,为了进行比较,Cython 的元组被转换为 Python 元组。


我个人会先使用 except * 看看它是否真的具有可衡量的影响。因为作为 cdef 函数显然可以与 Python 交互,所以添加更多一点可能根本没有坏处。

如果是这样,最好可能是更改函数的签名,例如

 cdef  int myFunction(int arg, (int, int) *a) except -1:
      ...
      return 0

即使这感觉不太顺畅 - 由于性能更好,可能值得麻烦。

关于python - 返回多个值的 cdef 函数的 Cython 异常传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66334531/

相关文章:

unit-testing - Unity 中的单元测试 - 获取 InvalidCastException - 为什么?以及如何解决?

c++ - 使用 Cython 和 distutilis 方法从 Python 调用 C++ 代码

python - 使用 SWIG 包装 C/C++ 库

python - python中实例变量和属性之间的区别?

java - 主方法抛出异常

c# - ArgumentOutOfRangeException 出现奇怪的本地化问题

python - PyInstaller 和 PySide,如何包含 imageformats 文件夹?

python - 为什么 logger.info() 只在调用 logging.info() 后出现?

Python Kivy 严重文本错误。无法找到任何有值(value)的文本提供者

python - CNN架构: classifying "good" and "bad" images