如何捕获Python subprocess.check_output调用C++程序抛出的异常?
如何让Python捕获C++程序的除零/浮点异常信息
你遇到的问题其实有两个核心原因,咱们一步步拆解解决:
首先,除零触发的是操作系统的硬件信号(SIGFPE),不是C++标准库的std::exception类型——你C代码里的catch(exception &e)根本抓不到这个错误!程序会直接被信号终止,返回的状态码-8就是SIGFPE的标识。其次,Python的check_output默认只捕获子进程的stdout,而你C里用cerr输出的内容是在stderr流里,默认没被捕获,所以看不到那行错误信息。
下面给出具体的解决方案:
第一步:修改C++代码,正确处理除零错误
有两种实用的方式可选:
方式1:手动检查除数,主动抛出标准异常
既然除零不会触发C++标准异常,那我们可以在计算前手动判断除数是否为0,主动抛出std::runtime_error,这样catch块就能正常捕获并输出信息:
#include<iostream> #include<exception> #include <stdexcept> using namespace std; int main() { int a=5; int b=0; try { cout<< "I am a statement before division"<< endl; // 手动检查除数,避免触发硬件信号 if (b == 0) { throw runtime_error("Floating point exception: division by zero"); } int c = a/b; cout<< "I am a statement after division"<< endl; } catch(const exception &e) { cerr << "Cerr - To test exception: " << e.what() << "\n" << endl; // 返回非零状态码,让Python感知到程序出错 return 1; } return 0; }
方式2:捕获SIGFPE信号
如果你不想手动检查所有可能的浮点错误,可以注册信号处理函数来捕获SIGFPE,输出错误信息后正常退出:
#include<iostream> #include<exception> #include <stdexcept> #include <signal.h> #include <unistd.h> using namespace std; void sigfpe_handler(int signum) { cerr << "Floating point exception (SIGFPE) caught!" << endl; // 退出程序并返回非零状态码 exit(1); } int main() { // 注册SIGFPE信号的处理函数 signal(SIGFPE, sigfpe_handler); int a=5; int b=0; try { cout<< "I am a statement before division"<< endl; int c = a/b; cout<< "I am a statement after division"<< endl; } catch(exception &e) { cerr << "Cerr - To test exception \n" << endl; return 1; } return 0; }
第二步:修改Python代码,捕获stderr输出
subprocess.check_output默认只捕获子进程的stdout,我们需要让它同时捕获stderr,这样才能拿到C++里cerr输出的内容。修改后的Python代码如下:
import subprocess import traceback print('Sample Python to simulate exception') TestOP = 'Default' try: # 把stderr合并到stdout一起捕获,同时设置universal_newlines让输出为字符串 TestOP = subprocess.check_output( ["/lhome/workspace/testException/testxptn"], stderr=subprocess.STDOUT, universal_newlines=True ) except subprocess.CalledProcessError as e : print(f"Command failed with return code {e.returncode}") print("Output from C++ program:") print(e.output) # 如果需要Python侧的栈追踪可以保留下面两行,否则可以注释掉 # tb = traceback.format_exc() # print(tb)
最终效果
修改后运行Python脚本,你会得到类似这样的输出(以方式1为例):
Sample Python to simulate exception I am a statement before division Command failed with return code 1 Output from C++ program: Cerr - To test exception: Floating point exception: division by zero
内容的提问来源于stack exchange,提问作者Be_bro
相关产品推荐
相关产品推荐

