:c:data:`PyExc_ValueError` is appropriate.
You can also define a new exception that is unique to your module.
-For this, you can declare a static global object variable at the beginning
-of the file::
+The simplest way to do this is to declare a static global object variable at
+the beginning of the file::
- static PyObject *SpamError;
+ static PyObject *SpamError = NULL;
-and initialize it with an exception object in the module's
+and initialize it by calling :c:func:`PyErr_NewException` in the module's
:c:data:`Py_mod_exec` function (:c:func:`!spam_module_exec`)::
+ SpamError = PyErr_NewException("spam.error", NULL, NULL);
+
+Since :c:data:`!SpamError` is a global variable, it will be overwitten every time
+the module is reinitialized, when the :c:data:`Py_mod_exec` function is called.
+
+For now, let's avoid the issue: we will block repeated initialization by raising an
+:py:exc:`ImportError`::
+
+ static PyObject *SpamError = NULL;
+
static int
spam_module_exec(PyObject *m)
{
+ if (SpamError != NULL) {
+ PyErr_SetString(PyExc_ImportError,
+ "cannot initialize spam module more than once");
+ return -1;
+ }
SpamError = PyErr_NewException("spam.error", NULL, NULL);
if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
return -1;
become a dangling pointer. Should it become a dangling pointer, C code which
raises the exception could cause a core dump or other unintended side effects.
+For now, the :c:func:`Py_DECREF` call to remove this reference is missing.
+Even when the Python interpreter shuts down, the global :c:data:`!SpamError`
+variable will not be garbage-collected. It will "leak".
+We did, however, ensure that this will happen at most once per process.
+
We discuss the use of :c:macro:`PyMODINIT_FUNC` as a function return type later in this
sample.