如何防止嵌入的Python退出我的进程

12 投票
2 回答
1471 浏览
提问于 2025-04-16 15:03

我在运行嵌入式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* 这一系列的函数。

撰写回答