error messages containing unicode
Steven D'Aprano
steve at REMOVEME.cybersource.com.au
Mon Jan 29 21:48:11 EST 2007
On Mon, 29 Jan 2007 18:01:56 -0800, Jim wrote:
> Hello,
>
> I'm trying to write exception-handling code that is OK in the
> presence
> of unicode error messages. I seem to have gotten all mixed up and
> I'd
> appreciate any un-mixing that anyone can give me.
[snip]
>>> class MyException(Exception): pass
...
>>> fn = u'a\N{LATIN SMALL LETTER O WITH DIAERESIS}k'
>>> raise MyException("hello")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyException: hello
>>>
Works fine with an ASCII argument, but not with Unicode:
>>> raise MyException(fn)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyException>>>
Notice the terminal problem? (The error message doesn't print, and the
prompt ends up stuck after the exception.)
Let's capture the exception and dissect it:
>>> try: raise MyException(fn)
... except Exception, err:
... print type(err)
... print err
...
<type 'instance'>
Traceback (most recent call last):
File "<stdin>", line 4, in ?
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in
position 1: ordinal not in range(128)
Now we have the answer: your exception (which just sub-classes Exception)
does the simplest conversion of Unicode to ASCII possible, and when it
hits a character it can't deal with, it barfs. That doesn't happen
until you try to print the exception, not when you create it.
The easiest ways to fix that are:
(1) subclass an exception that already knows about Unicode;
(2) convert the file name to ASCII before you store it; or
(3) add a __str__ method to your exception that is Unicode aware.
I'm going to be lazy and do a real simple-minded version of (2):
>>> class MyBetterException(Exception):
... def __init__(self, arg):
... self.args = arg.encode('ascii', 'replace')
... self.unicode_arg = arg # save the original in case
>>> raise MyBetterException(fn)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyBetterException: a?k
And now it works.
--
Steven D'Aprano
More information about the Python-list
mailing list