views:

96

answers:

3

I encountered a very strange behavior in Python, a behavior that is not consistent.

...
except IOError as msg:
    sys.exit("###ERROR IOError: %s" % (msg))

Usually this would get me a message like:

###ERROR IOError: [Errno 13] Permission denied: 'filename'

In same cases the above code is giving me a tuple instead of a proper error message.

###ERROR IOError: (13, 'Permission denied')

This is very strange because in all case the exception come from the same python method, codecs.open(...)

What makes me wonder more about this is that if I remove the handling the exception will reach upper levels with the right text (full error message), always!

except IOError as msg:
    print(msg)
    raise msg

The above example will always print a complete message, like IOError: [Errno 13] Permission denied: u'filename'.

Why is this happening and how do I prevent this, I don't want to give incomplete error messages to the users.

I wanted to reproduce this behavior in a test file, but I was not able to reproduce this outside the project.

I suspect that is has something to do with the usage of sys.exit() because print(msg) will give good result but sys.exit not.

+3  A: 

First, when reraising an exception, never do except Exc as e: raise e. It is always just plain raise with no arguments. This will preserve the traceback.

No, this has nothing to do with sys.exit and everything to do with how the exception was instantiated. You are always getting an exception; just sometimes its string representation will resemble that of a tuple.

>>> print IOError(13, 'Permission denied')
[Errno 13] Permission denied
>>> print IOError((13, 'Permission denied'))
(13, 'Permission denied')

Without showing the full traceback, there's no way to tell what exactly is raising the error in this way. Also, without properly reraising like I pointed out, you won't be getting the full traceback.

Aaron Gallagher
+1  A: 

Before Python 1.5 exceptions were strings. After that they changed it to classes to maintain backwards compatibility. Nowadays you can only raise exception instances or classes.

I imagine there was a code like this:

error = (13, 'Permision denied')

#more code

raise error

After they changed it to exception somebody just did:

raise IOError(error)
Kugel
A: 

I would suggest that you don't depend on the string representation of the exception; you might name it msg, but it's neither a string nor a message; it's an exception instance.

So you might want to construct your own string from the msg.args tuple, and use that as the “message” you want to display.

ΤΖΩΤΖΙΟΥ