[Python-Dev] [capi-sig] Exceptions with additional instance variables (original) (raw)

Guilherme Polo ggpolo at gmail.com
Mon Dec 22 13:48:46 CET 2008


On Mon, Dec 22, 2008 at 10:45 AM, Guilherme Polo <ggpolo at gmail.com> wrote:

On Mon, Dec 22, 2008 at 10:06 AM, <chojrak11 at gmail.com> wrote:

On Mon, Dec 22, 2008 at 03:29, Guilherme Polo <ggpolo at gmail.com> wrote:

On Sun, Dec 21, 2008 at 11:02 PM, <chojrak11 at gmail.com> wrote:

Hello,

I'm trying to implement custom exception that have to carry some useful info by means of instance members, to be used like: try: // some code except MyException, data: // use data.errorcode, data.errorcategory, data.errorlevel, data.errormessage and some others The question is - how to implement the instance variables with PyErrNewException? Using PyErrNewException is fine. You must understand that an exception is a class, and thus PyErrNewException creates one for you and returns it. Just like you would do with a class that has dict, set some attributes to what you want. That is, use PyObjectSetAttrString or something more appropriated for you. Ok so I did the following. In init function (forget refcounting and error checking for a moment ;-) PyObject *dict = PyDictNew(); PyDictSetItemString(dict, "errorcode", PyIntFromLong(0)); static PyObject *myexception = PyErrNewException("module.MyException", NULL, dict); You do not really have to create a dict here, one will be created for you if you pass a NULL there. PyModuleAddObject(module, "MyException", myexception); It worked more or less as expected, the help shown: | ---------------------------------------------------------------------- | Data and other attributes defined here: | | errorcode = 0 | | ---------------------------------------------------------------------- Then I did the following when raising the exception: PyObjectSetAttrString(myexception, "errorcode", PyIntFromLong(111)); PyErrSetString(myexception, "Bad thing happened"); return NULL; and the test code was: try: dobadthing(); except MyException, data: and you surely already guessed it -- data.errorcode was 0.... Not only that, module.MyException.errorcode was also 0... What I'm doing wrong? I certainly don't get the idea of exceptions in Python, especially what is being raised - a class or an instance? There are two forms raise can take, both will end up involving a class and a intsance. If the latter - how's the class instantiated? You can call a class to instantiate it. If not - what about values in different threads? The docs are so vague about that... Thanks again in advance, Chojrak Again, an exception is a class, so you could create a new type in C, and do anything you wanted. But you probably don't want to create a new type to achieve this

By creating a type I mean one that involves defining a tp_init, and everything else your type needs, not about the simple one created by PyErr_NewException.

, so there are two simple ways I'm going to paste below:

#include "Python.h" static PyObject *MyErr; static PyMethodDef modulemethods[] = { {"raisetest", (PyCFunction)raisetest, METHNOARGS, NULL}, {NULL}, }; PyMODINITFUNC initfancyexc(void) { PyObject *m; m = PyInitModule("fancyexc", modulemethods); if (m == NULL) return; MyErr = PyErrNewException("fancyexc.err", NULL, NULL); PyINCREF(MyErr); if (PyModuleAddObject(m, "err", MyErr) < 0) return; } the raisetest function is missing, pick one of these: static PyObject * raisetest(PyObject *self) { PyObjectSetAttrString(MyErr, "code", PyIntFromLong(42)); PyObjectSetAttrString(MyErr, "category", PyStringFromString("nice one")); PyErrSetString(MyErr, "All is good, I hope"); return NULL; } or static PyObject * raisetest(PyObject *self) { PyObject *t = PyTupleNew(3); PyTupleSetItem(t, 0, PyStringFromString("error message")); PyTupleSetItem(t, 1, PyIntFromLong(10)); PyTupleSetItem(t, 2, PyStringFromString("category name here")); PyErrSetObject(MyErr, t); PyDECREF(t); return NULL; } In this second form you check for the args attribute of the exception. -- -- Guilherme H. Polo Goncalves

-- -- Guilherme H. Polo Goncalves



More information about the Python-Dev mailing list