如何防止嵌入的Python退出我的进程
我在运行嵌入式Python时遇到了一些麻烦。结果发现,我无法捕捉到由sys.exit()引发的SystemExit异常。
这是我目前的代码:
$ cat call.c
#include <Python.h>
int main(int argc, char *argv[])
{
Py_InitializeEx(0);
PySys_SetArgv(argc-1, argv+1);
if (PyRun_AnyFileEx(fopen(argv[1], "r"), argv[1], 1) != 0) {
PyObject *exc = PyErr_Occurred();
printf("terminated by %s\n",
PyErr_GivenExceptionMatches(exc, PyExc_SystemExit) ?
"exit()" : "exception");
}
Py_Finalize();
return 0;
}
另外,我的脚本是:
$ cat unittest-files/python-return-code.py
from sys import exit
exit(99)
运行它时:
$ ./call unittest-files/python-return-code.py
$ echo $?
99
我必须执行一个文件,而不是一个命令。
2 个回答
0
根据Denis的回答,我写了一个代码片段:
PyObject* main_module = PyImport_AddModule("__main__");
if (!main_module) {
PyErr_Print();
// Failure
} else {
Py_INCREF(main_module);
PyObject *pdict = PyModule_GetDict(main_module);
if (PyRun_File(file, file_name, Py_file_input, pdict, pdict) != NULL) {
// Success
} else {
Py_CLEAR(main_module);
PyObject *exception_type = PyErr_Occurred();
if (!PyErr_GivenExceptionMatches(exception_type, PyExc_SystemExit)) {
PyErr_Print();
// Failure
} else {
PyObject *type;
PyObject *value;
PyObject *traceback;
PyErr_Fetch(&type, &value, &traceback);
long exit_code = PyLong_AsLong(value);
std::cout << exit_code << std::endl;
if (exit_code == 0) {
// Success
} else {
// Failure: sys.exit() with non-zero code
}
Py_XDECREF(type);
Py_XDECREF(value);
Py_XDECREF(traceback);
}
}
Py_XDECREF(main_module);
}
8
PyRun_SimpleFileExFlags
这个函数(还有所有使用它的函数,比如 PyRun_AnyFileEx
)会自己处理错误。如果遇到 SystemExit
的情况,它会直接退出;如果是其他错误,它会打印出错误的详细信息。想要在周围的代码中处理错误,可以使用 PyRun_File*
这一系列的函数。