6

Why doesn't this work?

try:
    1/0
except ZeroDivisionError as e:
    e.message += ', you fool!'
    raise

The modified message is not used, even though it remains on the exception instance. Is there a working pattern for the above? Behaviour should be like my current workaround below:

try:
    1/0
except ZeroDivisionError as e:
    args = e.args
    if not args:
        arg0 = ''
    else:
        arg0 = args[0]
    arg0 += ', you fool!'
    e.args = (arg0,) + args[1:]
    raise

I'm aware of exception chaining in python3, it looks nice but unfortunately doesn't work in python2. So what is the usual recipe for re-raising an exception in python2?

Note: Because of the warnings and caveats mentioned here, I don't want to dig up the traceback and create a new exception but rather re-raise the existing exception instance.

wim
  • 338,267
  • 99
  • 616
  • 750

2 Answers2

4

Changing e.args is the only way to do this. The implementation for BaseException.__str__ only considers the args tuple, it doesn't look at message at all:

static PyObject * 
BaseException_str(PyBaseExceptionObject *self)
{
    PyObject *out;

    switch (PyTuple_GET_SIZE(self->args)) { 
    case 0:
        out = PyString_FromString("");
        break;
    case 1:
        out = PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
        break;
    default:
        out = PyObject_Str(self->args);
        break;
    } 

    return out;
}

This shouldn't be too unexpected, since BaseException.message is deprecated since Python 2.6.

Community
  • 1
  • 1
dano
  • 91,354
  • 19
  • 222
  • 219
0

I don't think there's going to be a better solution than your workaround. ZeroDivisionError doesn't use the message property to build its output, so modifying that will have no effect.

If you're specifically catching a ZeroDivisionError it should always have a single argument so the following more succinct version will work:

try:
    1/0
except ZeroDivisionError as e:
    e.args = (e.args[0] + ', you fool!',)
    raise

If you check the properties of ZeroDivisionError, all it has are args and message and it doesn't use message so short of creating a new error, modifying args is pretty much the only possible solution.

Julian
  • 2,483
  • 20
  • 20