Suppose I have an exception e
, and I would like to format it for logging/printing:
def format_exception(e):
# type: (Exception) -> Text
"""Log formatter used in a catch-all near the edge."""
return str(e) # Python 2.7 only
Specifically, I want to get the exception message - the equivalent of e.message
in Python 2.6, or str(e)
in Python 2.7.
I have tried
return six_text_type(e)
However, that fails if e.message
contains encoded bytes (which, given that I am working in a py2-py3 environment, can happen.)
>>> six.text_type(MyError(u'')) # OK
>>> six.text_type(MyError(u''.encode('utf-8')))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 0: ordinal not in range(128)
traceback.format_exception_only
(from related question) does almost the right thing (handles both bytes and unicode), but it forces me to split on :
. It also doesn't help that format_exception_only
returns a byte string in python2, and a unicode string in python3.
# python2
>>> type(traceback.format_exception_only(type(e), e)[0])
str
# python3
>>> type(traceback.format_exception_only(type(e), e)[0])
str
So that doesn't quite work. Wrapping that in six.text_type
again fails if e.message
contains encoded bytes.
What's the right way to fill in format_exception
? Do I really need to use traceback2
?
def format_exception(e):
# type: (Exception) -> Text
return traceback2.format_exception_only(type(e), e)[0].split(': ')[1]
I can install and use traceback2
, but it feels like there should be a better way.