如何正确使用Python的C API和异常?

dej*_*jay 12 c python api python-c-api

如果我做的事情

 >>> x = int(1,2,3,4,5)
Run Code Online (Sandbox Code Playgroud)

我立即得到一个致命的错误(如果它是在一个预先编写的脚本中就会结束程序执行)

 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: int() takes at most 2 arguments (5 given)
Run Code Online (Sandbox Code Playgroud)

并且x仍未定义:

 >>> x
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 NameError: name 'x' is not defined
Run Code Online (Sandbox Code Playgroud)

我将如何在Python的C API中实现它?我找到了一些文档,但我不确定我是否知道如何正确使用它.

这是我一直在尝试的:

  1. 打印:

    if(something) {
        PyErr_SetString(PyExc_TypeError, "Oh no!");
        PyErr_Print();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    遗憾的是,这只会打印异常并继续执行程序.另外,如果我理解正确 - PyErr_Print()从某种队列中删除异常,因此Python认为它已被处理.这就是它的样子:

    >>> import awesomemod
    >>> x = awesomemod.thing()
    TypeError: Oh no!
    >>> x # x is defined because the function returns None eventually
    >>> 
    
    Run Code Online (Sandbox Code Playgroud)
  2. PyErr_Occurred():

    if(something) {
        PyErr_SetString(PyExc_TypeError, "Oh no!");
        PyErr_Occurred();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    行为:

    >>> import awesomemod
    >>> awesomemod.thing()
    >>>
    TypeError: Oh no!
    >>>
    
    Run Code Online (Sandbox Code Playgroud)

    所以它有点晚了...

  3. return PyErr_Occurred():

    if(something) {
        PyErr_SetString(PyExc_TypeError, "Oh no!");
        return PyErr_Occurred();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    行为:

    >>> import awesomemod
    >>> awesomemod.thing()
    <type 'exceptions.TypeError'>
    >>>
    TypeError: Oh no!
    
    Run Code Online (Sandbox Code Playgroud)

    这个真的很奇怪.

我需要做些什么才能获得内置函数的行为?

编辑:我尝试了@ user2864740在评论中建议的内容,它完美无缺!

 if(something) {
     PyErr_SetString(PyExc_TypeError, "Oh no!");
     return (PyObject *) NULL;
 }
Run Code Online (Sandbox Code Playgroud)

Ign*_*ams 9

在C中引发异常是通过设置异常对象或字符串然后NULL从函数返回来完成的.


Jon*_*art 5

正如伊格纳西奥·巴斯克斯·艾布拉姆斯所说

在 C 中引发异常是通过设置异常对象或字符串然后从函数返回 NULL 来完成的。

对于常见的异常类型,有一些方便的函数可以轻松做到这一点。例如,PyErr_NoMemory可以这样使用:

PyObject *my_function(void)
{
    return PyErr_NoMemory();  // Sets the exception and returns NULL
}
Run Code Online (Sandbox Code Playgroud)