MadBlack
MadBlack

Reputation: 327

C++ calling Python how to deal with SystemExit exception

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

Upvotes: 2

Views: 377

Answers (2)

MadBlack
MadBlack

Reputation: 327

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

Upvotes: 0

Szabolcs Dombi
Szabolcs Dombi

Reputation: 5783

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.

Upvotes: 1

Related Questions