Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

call PyErr_SetString twice without clearing

I have a C++ function to parse python strings:

std::string parse_string(PyObject* py_string) { 
  std::string out; 
  if (!PyString_Check(py_string)) { 
    PyErr_SetString(PyExc_TypeError,"expected a string");
    return out; 
  }
  out = PyString_AsString(py_string); 
  return out; 
}

I'm calling the function from a python wrapper:

PyObject* some_func(PyObject* self, PyObject* args) { 
// ...
  std::string my_first_string = parse_string(first_py_string);
  if (PyErr_Occurred()) { 
    PyErr_SetString(PyExc_TypeError,"more verbose error for this string"); 
    return 0; 
  }
  std::string my_second_string = parse_string(second_py_string);
  if (PyErr_Occurred()) { 
    PyErr_SetString(PyExc_TypeError,"some other error for this string"); 
    return 0; 
  }
// ...
}

This will throw a python exception as desired, but I'm worried about calling PyErr_SetString again to give the more verbose message. Will it cause a leak?

like image 532
Shep Avatar asked Feb 11 '26 03:02

Shep


1 Answers

According to Python Extension Patterns, it's okay to set exceptions multiple times in a single call stack. Only the last one will be set and thrown when you return to Python.

The other thing to note is that if there are multiple calls 
to PyErr_SetString only the last one counts:

static PyObject *_raise_error_overwrite(PyObject *module) {
    PyErr_SetString(PyExc_RuntimeError, "FORGOTTEN.");
    PyErr_SetString(PyExc_ValueError, "ERROR: _raise_error_overwrite()");
    assert(PyErr_Occurred());
    return NULL;
}
like image 128
jschultz410 Avatar answered Feb 13 '26 16:02

jschultz410