12

I'm having trouble while running embedded python. It turns out that I can't capture that SystemExit exception raised by sys.exit();

This is what I have so far:

$ 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;
}

Also, my script is:

$ cat unittest-files/python-return-code.py 
from sys import exit
exit(99)

Running it:

$ ./call unittest-files/python-return-code.py 
$ echo $?
99

I must execute a file, not a command.

2 Answers 2

8

PyRun_SimpleFileExFlags function (and all functions using it, including PyRun_AnyFileEx) handles exceptions itself by exiting for SystemExit or printing traceback. Use PyRun_File* family of functions to handle exceptions in surrounding code.

Sign up to request clarification or add additional context in comments.

1 Comment

Nice solution. Now using PyRun_FileEx() and checking PyErr_Occurred() before PyErr_GivenExceptionMatches(). Thanks.
0

Based on Denis' answer, here is a code snippet that I've came up with:

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);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.