C++ calling Python how to deal with SystemExit exception

Viewed 197

I have a C++ code which executes Python script using the PyRun_SimpleFileEx C API.

The py file looks like this

import time

time.sleep(2)
raise SystemExit("Sorry, it is time to exit.")

SystemExit is what is also raised by calling python stuff like either quit() or abort()

Since SystemExit inherits from BaseException instead of Exception it is not catched and shuts-off the Python environment as well as the C++ application.

Is there any way to catch the exception above from C++?

Thanks in advance All the best MB

2 Answers

You can create a wrapper.py and run the code from it.

class ExceptionWrapper(Exception):
    def __init__(self, exc):
        self.exc = exc

def run_code(filename):
    try:
        exec(open(filename).read(), globals=globals(), locals=locals())
    except BaseException as ex:
        raise ExceptionWrapper(ex)

Using this wrapper from C++:

#include <Python.h>

int main() {
    Py_Initialize();
    PyObject * wrapper = PyImport_ImportModule("wrapper");
    if (!wrapper) {
        PyErr_Print();
        exit(1);
    }
    PyObject * res = PyObject_CallMethod(wrapper, "run_code", "s", "simple.py");
    if (!res) {
        PyErr_Print();
        // PyObject *type, *value, *traceback;
        // PyErr_Fetch(&type, &value, &traceback);
        // PyErr_NormalizeException(&type, &value, &traceback);
        // or handle exception manually here
        // PyErr_Restore(type, value, traceback);
    }
    Py_XDECREF(res);
    printf("exit from C\n");
}

Please note that this is just a POC and it is not safe to run arbitrary code.

You can modify the wrapper to accept a file descriptor as argument.

Maybe it will turn useful to someone else:

using the PyRun_File* C API family makes the outer C++ application to stay in place (no shut-off).

The script will fail and the PyObject pointer returned by the function will be invalid to indicate that

Related