PyErr_SetString不会立即引发异常(Swig)?

时间:2013-12-20 20:38:47

标签: python c swig

我使用SWIG将C lib包装到python模块。但似乎没有在正确的地方引发异常,我有一个简单的演示,

except_test.i

%module except_test


%{
#include "except_test.h"
#include <stdio.h>
%}

%{
static int flagged_exception = 0;

void throw_except()
{
    flagged_exception = 1;
    printf("flag set \n");
}
%}

%exception {
    $action
    printf("exception block\n");
    if (flagged_exception) {
        printf("before setstring\n");
        PyErr_SetString(PyExc_RuntimeError, "test except");
        printf("after setstring\n");
        flagged_exception = 0;
    }
}
%include "except_test.h"

except_test.c

#include "except_test.h"


int except_test(int a) {

    if (a < 0) {
        throw_except();
        return 0;
    } else{
        return -1;
    }
}

run_except.py

from except_test import *
import time

def test():
    b = except_test(-1)
    print 'b=', b

try:
    test()
except:
    print "caught exception"

for i in range(10):
    print i
    time.sleep(1)

现在如果我运行run_except.py

$python run_except.py 
flag set 
exception block
before setstring
after setstring
b= 0
0
Traceback (most recent call last):
  File "run_except.py", line 15, in <module>
    time.sleep(1)
RuntimeError: test except

如输出所示,try / catch块没有捕获异常。 为什么是这样?以及如何避免这种情况?

谢谢,

2 个答案:

答案 0 :(得分:3)

您必须从Python扩展程序返回NULL才能立即注意到错误:

if (flagged_exception) {
    PyErr_SetString(PyExc_RuntimeError, "test except");
    flagged_exception = 0;
    return NULL;
}

但是使用通用SWIG宏将使SWIG接口更易于移植到其他语言。

答案 1 :(得分:2)

您需要在SWIG_fail;之后立即PyErr_SetString。或者,有一个方便的(以及更重要的与语言无关的)宏SWIG_exception(SWIG_RuntimeError, "error message")包裹PyErr_SetStringSWIG_fail