Search code examples
python-2.7python-3.xpython-unicode

Python 2.7 exception do not handle unicode in python3 compatible code ('<exception str() failed>')


I'm trying to have a python2.7/3+ compatible code. And I'm struggling to handle raising a ValueError with a message in unicode correctly. I found very little results for "exception str() failed".

Here's the code:

from __future__ import (
    absolute_import, division, print_function, unicode_literals
)

import logging

from builtins import str
from future import standard_library

standard_library.install_aliases()

conf = {}
try:
    conf["key"]
except KeyError:
    msg = "Message"
    msg += " + ünicode"
    logging.warn(msg)
    raise ValueError(msg)

In python3 this is working as expected, but in python 2.7 as soon as msg contain unicode it gives:

WARNING:root:Message + ünicode
Traceback (most recent call last):
  File "<stdin>", line 7, in <module>
ValueError: <exception str() failed>

Notice how the logging can handle the unicode string but not ValueError. What am I doing wrong ? How can I have a unicode error message in both python 2.7 and 3+ ?


Solution

  • You can try to encode the msg convert it to string for Python 2, e.g.

    from sys import version_info
    
    if version_info.major == 2:
        raise ValueError(msg.encode('utf-8'))
    elif version_info.major == 3:
        raise ValueError(msg)
    else:
        raise YourException("not supported Python version")
    

    Upate: Below is the workaround without importing any package if you only use from __future__ import unicode_literals without python-future package:

    if isinstance(msg, str):
       raise ValueError(msg)
    else:
       raise ValueError(msg.encode('utf-8'))
    

    Wait for patch from Python code level(e.g. six, future package) is nearly impossible as the problematic code is in C code level in pythonrun.c, it seems like PyObject_Str(value) execution for unicode string returned null