您正在混合unicode和str对象。
说明:
在Python2.x中,有两种对象可以包含文本字符串。str和unicode。str是一个字节字符串,因此它只能包含0到255之间的字符。
Unicode是Unicode字符的字符串。
可以使用“encode”和“decode”方法在str和unicode之间进行转换:>>> "thisisastring".decode('ascii')
u'thisisastring'
>>> u"This is ä string".encode('utf8')
'This is \xc3\xa4 string'
注意编码。编码是将unicode文本表示为字节字符串的方法。
如果尝试将str和unicode添加到一起,Python将尝试将其中一个转换为另一个。但默认情况下,它将使用ASCII作为编码,这意味着a-z、a-z和一些额外的字符,如!"#$%&/()=?'{[]]}等。其他任何字符都将失败。
此时,您将得到一个编码错误或解码错误,这取决于Python是否尝试将unicode转换为str或str转换为unicode。通常它会尝试解码,即转换为unicode。但有时它决定不去,而是强迫去串。我不完全确定为什么。
更新:
上面出现编码错误而不是解码错误的原因是上面代码中的message既不是str也不是unicode。它是另一个对象,它有一个str方法。因此,Python在传入str(message)之前会执行str(message),但这会失败,因为内部存储的消息是一个不能强制转换为ascii的unicode对象。
或者更简单的回答是:它失败是因为warnings.warn()不接受unicode消息。
现在,解决方案:
不要混合str和unicode。如果你需要使用unicode,而且你显然需要,那么试着确保所有的字符串都是unicode。这是确保你避免这种情况的唯一方法。这意味着,无论何时从磁盘读取字符串,或调用可能返回纯ascii str以外任何内容的函数,都应尽快将其解码为unicode。
当您需要将它保存到磁盘或通过网络发送或传递给不理解unicode的方法时,请尽可能晚地将其编码到str。
在这种特定情况下,问题是您将unicode传递给warnings.warn(),而您不能这样做。传递字符串。如果您不知道它是什么(这里似乎是这样),因为它来自其他地方,您的try/except解决方案与repr一起工作很好,尽管做一个编码是可能的。