Search code examples
pythoncexceptionpython-c-extension

PyErr_Set* twice


Is it safe to call PyErr_Set* to override an exception? According to the docs, PySequence_Fast raises a TypeError with the const char * message argument supplied to it if there's an error. Would it be safe to call PyErr_SetObject after PySequence_Fast raises an error?

Example:

static PyObject * myfunc(PyObject * self, PyObject * args) {
    PyObject * pyobj;
    PyObject * pyseq;
    PyObject * message;

    if (!PyArg_ParseTuple(args, "O", &pyobj)) {
        return NULL;
    }

    pyseq = PySequence_Fast(pyobj, "");
    if (pyseq == NULL) {
        message = PyString_FromFormat("argument is a '%s', not a sequence.", pyobj->ob_type->tp_name);
        PyErr_SetObject(PyExc_TypeError, message);
        Py_XDECREF(message);
        return NULL;
    }

    // ...
}

Solution

  • According to "Python/errors.c" from the Python 2.7.2 source code, PyErr_SetObject() calls PyErr_Restore() which Py_XDECREF()s any old exception state variables before setting the new ones. So yes, it is safe to override an existing exception. Just be aware that you are completely overriding the previous exception.