Type checking inside a C extension... doesn't throw exception on failure

Tim Peters tim.one at comcast.net
Wed Apr 7 01:07:56 EDT 2004


[Andrew MacIntyre]
>> First rule of using the Python C API: _always_ check the return
>> value of API functions.

[Jon Perez]
> This only applies to API functions which return PyObject*, right?

No, it applies to all API functions that return a value (not all do).

> ...because it is not hard to find instances in the source code for
> the modules that come with Python where, for example,
> PyTuple_SetItem()'s return value is not checked for.

Strictly speaking, those are bugs in the core, and are mostly in very old
modules.  When new code is written in the core that wants to skip the error
checks done by PyTuple_SetItem, because it "knows" nothing can go wrong, it
uses the macro PyTuple_SET_ITEM instead.  All non-checking uses of
PyTuple_SetItem() should be reviewed for correctness, and replaced with
PyTuple_SET_ITEM() invocations instead whenever they are in fact provably
correct (or changed to check the return value when they're not provably
correct).

Even API functions that return ints or doubles need to be checked!  In those
cases, there may not be an unambiguous "this is an error return" value, and
then fancier code is needed; e.g., long_float's

static PyObject *
long_float(PyObject *v)
{
	double result;
	result = PyLong_AsDouble(v);
	if (result == -1.0 && PyErr_Occurred())
		return NULL;
	return PyFloat_FromDouble(result);
}

There are at least 3 ways in which PyLong_AsDouble() can fail, but -1.0 is
also a legitimate return value, so PyErr_Occurred() is needed to distinguish
"-1.0 is a normal return" from "-1.0 is an error return".





More information about the Python-list mailing list