Python UnicodeDecodeError - 我是否误解了编码?
你们觉得为什么这个不管用呢?我真的以为'ignore'会起作用的。
>>> 'add \x93Monitoring\x93 to list '.encode('latin-1','ignore')
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 4: ordinal not in range(128)
4 个回答
这里有一行神奇的代码:
unicodedata.normalize('NFKD', text).encode('utf-8', 'ignore')
这行代码在最需要的时候不会引发错误(比如去掉那些坏的Unicode字符...)
encode这个功能是可以用在unicode字符串上的,但你这里的字符串看起来并不是unicode格式的(可以试试用u'add \x93Monitoring\x93 to list '这个方式)。
>>> u'add \x93Monitoring\x93 to list '.encode('latin-1','ignore')
'add \x93Monitoring\x93 to list '
… 这就是为什么它们叫“编码”的原因 …
先说一下背景:把Unicode想象成一个标准,或者说是理想状态。Unicode其实就是一个字符表。比如,编号65是拉丁字母的大写A,编号937是希腊字母的大写欧米伽。就这么简单。
为了让电脑能够存储和处理Unicode,它需要把这些字符编码成字节。最简单的Unicode编码方式是UCS-4;每个字符占用4个字节,所有大约100万个字符都可以用。4个字节里存的是字符在Unicode表中的编号,作为一个4字节的整数。还有一种非常实用的编码方式是UTF-8,它可以用1到4个字节来编码任何Unicode字符。不过也有一些限制比较大的编码,比如“latin1”,它只包含非常有限的字符范围,主要用于西方国家。这种编码每个字符只用一个字节。
总的来说,Unicode可以用很多种编码方式来表示,而编码后的字符串又可以解码回Unicode。问题是,Unicode出现得比较晚,所以我们这些在8位字符集中长大的人,直到很晚才意识到自己一直在处理编码后的字符串。这个编码可能是ISO8859-1,或者windows CP437,或者CP850,等等,具体取决于我们的系统默认设置。
所以,当你在代码里输入字符串“add “Monitoring“ to list”(我想你想要的是“add “Monitoring” to list”,注意第二个引号),实际上你使用的是一个已经根据系统默认代码页编码过的字符串(通过字节\x93,我猜你用的是Windows代码页1252,“西方”)。如果你想从中得到Unicode,你需要把这个字符串从“cp1252”编码解码过来。
所以,你本来想做的是:
"add \x93Monitoring\x94 to list".decode("cp1252", "ignore")
很遗憾,Python 2.x也有一个.encode
方法用于字符串;这个方法是为了“特殊”编码提供的,比如“zip”或“rot13”或“base64”,这些和Unicode没有关系。
无论如何,你只需要记住进行Unicode转换时的要点:
- 一个Unicode字符串会被编码成Python 2.x字符串(实际上是字节序列)
- 一个Python 2.x字符串会被解码成Unicode字符串
在这两种情况下,你都需要指定将要使用的编码。
我说得不太清楚,可能有点困,但我希望能帮到你。
附注:有趣的一点是:玛雅人没有Unicode;古罗马人、古希腊人、古埃及人也没有。他们都有自己的“编码”,对其他文化几乎没有尊重。这些文明最终都消失了。大家想想吧!为了人类的未来,让你的应用程序支持Unicode。:)
附注2:请不要因为“但是中国…”而破坏前面的信息。如果你真的想说,可以先想想Unicode的基本多语言平面(BMP)主要是由汉字构成的,因此汉字是Unicode的基础。我可以继续编造一些离谱的谎言,只要人们能开发支持Unicode的应用程序。