Errors in the Method Wrapper and How to Handle Them - danecross/PyNA62Analysis GitHub Wiki
This is a good reference if you want more information.
C and C++ errors are famously not helpful. Python errors are slightly more helpful, if anything more verbose. This way of error handling is not only stylistic, it's a convention. So we must take care to ensure that errors are handled properly.
The convention is as follows (from Python Docs): when a function fails, it should set an exception condition and return an error value (usually a NULL pointer, sometimes -1, etc). The Python interpreter stores three variables when an exception is thrown: one stores the exception itself, another stores the "associated value" of the exception (basically a more detailed report of why the error occurred), and yet another stores the stack traceback (ie the lines of the code where all of the calls were made).
The main issue I see with this project specifically is that scientists usually do not handle industrial code, so the error values and information will probably be pretty useless. I think Dr. Rubin gave us the go-ahead to alter the code a little so that it integrates better. Error handling might be an important use of this privilege.
The Python API (<Python.h>) has many functions that set the exception variables in the interpreter. Here are a few popular ones:
-
PyErr_SetString(PyObject *type, const char *message)
- The PyObject should be an Exception Object and the char argument is for the "associated value" information.
When a function f calls another function g, and g fails, f should itself return an error value. It should not call another PyErr_*() function. This is so that when the Python interpreter reads an error value, it has the correct stack traceback and returns the correct error.
Every failing malloc()
or realloc()
must be caught with a PyErr_NoMemory() exception and return an error value.
When you return an error value, do not forget to call Py_XDECREF()
or Py_DECREF()
so that all of the garbage is cleaned up.