2016-03-08 29 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沒有。 –