【问题标题】:PyErr_SetString does not raise the exception immediately(Swig)?PyErr_SetString 不会立即引发异常(Swig)?
【发布时间】:2013-12-20 20:38:47
【问题描述】:

我正在使用 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 块没有捕获异常。 为什么是这样?以及如何避免这种情况?

谢谢,

【问题讨论】:

  • 查看 _wrap.c 文件中生成的代码。 %exception 中的代码在那里吗?

标签: python c swig


【解决方案1】:

你必须从 Python 扩展返回 NULL 让它立即注意到错误:

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

但使用通用 SWIG 宏将使 SWIG 界面更易于移植到其他语言。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多