Python,UnicodeDecodeError试图打印包含非ascii字符的异常

时间:2014-12-26 04:21:34

标签: python python-2.7 unicode encoding utf-8

当我得到cPickle.UnpicklingError: invalid load key, 'ÿ'.的异常并且我尝试打印它时,当我尝试将其插入到我的(unicode)错误消息中时,它会引发unicode解码错误:

try:
    settings = _load()
except cPickle.UnpicklingError, err:
    msg = _(u"Error reading ... (the error is: '%s')")
    cont = askYes(msg % err, _(u"Settings Load Error")) # raises

尝试了msg % unicode(err.message, encoding='utf-8')中的变通方法,但显然err.message是无效的unicode字符串(“UnicodeDecodeError:'utf8'编解码器无法解码位置19的字节0xff:无效的起始字节”)

那么处理这个问题最灵活的方法是什么?我应该将'ignore'或'replace'传递给unicode()吗?

编辑:askYes(None, msg % repr(err), _(u"Settings Load Error"))提供类似的内容:

(the error is: 'UnpicklingError("invalid load key, '\xff'.",)'). # ff is ÿ

不吹,但仍然......

Edit2:我报告的错误与人为错误有点混淆:

u'%s' % "cPickle.UnpicklingError: invalid load key, 'ÿ'."
Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 44: ordinal \
    not in range(128)

这是来自pycharm内部的解释器 - 显然ÿ'\xc3\xbf'那里(...)

2 个答案:

答案 0 :(得分:3)

确保您可以在错误消息中看到结果的一种方法是使用repr或更直接%r而不是%s:永不失败(因为任何对象都有表示,并且所有表示都是ASCII,包括可能的转义序列),并且还显示(作为转义序列)可能不可见的字符。

repr(以及旧式格式字符串中的'%r')委托给对象类型的__repr__特殊方法;每个对象类型负责知道如何在一个明确的(不一定是超可读的)ASCII字符串中最好地表示自己。字符串和字节序列特别擅长,因此repr非常适合它们。

OP已经这样做但不喜欢结果的美学(在repr err.messagerepr err的{​​{1}}之间变化。不幸的是,美学是repr的最重要的优先事项:相反,它完全是关于完整,明确的信息。

另一个想法是使用永不失败的编码进行解码(一个解码每个字节,但可能解码为无意义的上下文字形),例如&#39; iso-8859-1&#39;。但我认为,与repr相比,它没有真正的改进;美学方面的改进是值得商榷的,并且有可能在完整,明确的信息方面造成损失。

答案 1 :(得分:0)

只是为了澄清一些观点:

Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32
>>> u'%s' % "cPickle.UnpicklingError: invalid load key, 'ÿ'."
Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 44: ordinal not in range(128)

这是因为python 2有助于解码字符串以将其插入到unicode字符串中 - 默认编码为ASCII - 当然ascii无法解码'ÿ'(解码意味着将字节转换为代码点) - 因此例外。下面的工作原理是它不会尝试解码任何东西 - 只显示字节 - 在ascii:

>>> '%s' % "cPickle.UnpicklingError: invalid load key, 'ÿ'."
"cPickle.UnpicklingError: invalid load key, '\xc3\xbf'."

下面也可以工作,并且(如ascii中的控制台显示)显示unicode字节值(即编码 unicode字符串 - 其中的字节 - 到ascii字符):

>>> u'%s' % u"cPickle.UnpicklingError: invalid load key, 'ÿ'."
u"cPickle.UnpicklingError: invalid load key, '\xff'."

与以下相同的逻辑:

>>> u'á, é, í, ó, ú, ü, ñ'
u'\xe1, \xe9, \xed, \xf3, \xfa, \xfc, \xf1'
>>> 'á, é, í, ó, ú, ü, ñ'
'\xc3\xa1, \xc3\xa9, \xc3\xad, \xc3\xb3, \xc3\xba, \xc3\xbc, \xc3\xb1'

正是这种内部编码/解码使我感到困惑 - 并且仍然让我感到困惑。