2016-03-08 30 views
0

说我有形式.so的Python模块,它包含了这样的事情:如何捕捉用C编写的python模块的运行时错误?

static PyObject* f(PyObject* _1, PyObject* _2) { 
    int a = 0; 
    a = 1/a; 
    return NULL; 
} 

运行Python会崩溃之后。命令行给出Floating point exception: 8

而且我也看到了这一点:

Python Crash

这是一个bug或者是有可能赶不改变这个错误并重新编译.so文件?

+1

对于源自C代码的错误,您必须使用C的设施。 –

+0

相关:http://stackoverflow.com/questions/3286448/calling-a-python-method-from-cc-and-extracting-its-return-value –

+0

添加到@ivan_pozdeev,当你写C扩展时,它是_your_工作来创造Python的异常提升。在调用非Python API时,您是唯一具有创建异常所需信息的人。 – ShadowRanger

回答

1

现在坐下来回忆一下C代码在运行时的样子。它只是编译成机器码。当它除以零时,在机器代码级别上发生- 即CPU实际尝试它,生成OS处理并最终终止您的进程的硬件中断。

另一方面,Python代码在运行时只是随机的二进制数据,即另一个代码 - 解释器 - 查看并确定要执行的操作。当您除以零时,解释器将检查除数并在之前打印一个很好的回溯CPU实际尝试操作。 数组边界,对象引用等也是如此。

简而言之,在C级别,没有Python解释器来保护你。您需要自己检查输入的有效性(对于源自Python运行时的输入,但是有库函数可以缓解任务)。同样,如果你想向Python运行时报告一个错误,你需要构造你自己,并向它传递一个具有相关信息(异常类型和参数)的异常对象,这里还有一堆库函数。

+0

你是说'try ... catch'实际上试图检测错误而不是CPU引发的捕获信号并处理它?这对我来说似乎有点奇怪。我可以想象它会检查索引是否超出范围。但是如果错误实际发生了(例如'MemoryError'或创建套接字失败)呢?在那种情况下,口译员仍然在做保姆工作? –

+0

@h__解释器的确在C级别上检测来自系统的错误 - 通过返回库函数的值,信号等,通过“捕获信号” - 构造和使用异常对象等。对于内存不足的情况,有[PyErr_NoMemory '](https://docs.python.org/2/c-api/exceptions.html#c.PyErr_NoMemory),可以在无法分配的情况下工作。是的,_every_'malloc'被选中。除以零是一个特例,因为[没有办法在C中捕捉它](http://stackoverflow.com/questions/3105591/how-to-catch-the-integer-division-by-zero-exception-in -c语言)。 –

+0

......哦,没有_standard_方式。大多数UNIX发送SIGFRE,并且[Windows抛出一个SEH异常](http://stackoverflow.com/questions/1832809/how-to-catch-divide-by-zero-error-in-visual-studio-2008- C)。我必须承认我没有真正检查Python究竟是如何处理这种情况的。重要的部分是,虽然C没有。 –