可能重复:
Python UnicodeDecodeError - Am I misunderstanding encode?
我有一个字符串,我正在努力使unicode()
函数安全:
>>> s = " foo “bar bar ” weasel"
>>> s.encode('utf-8', 'ignore')
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
s.encode('utf-8', 'ignore')
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 5: ordinal not in range(128)
>>> unicode(s)
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
unicode(s)
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 5: ordinal not in range(128)
我大部分都在这里挥舞着。如何从字符串中删除不安全的字符?
与此question有些相关,虽然我无法解决我的问题。
这也失败了:
>>> s
' foo \x93bar bar \x94 weasel'
>>> s.decode('utf-8')
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
s.decode('utf-8')
File "C:\Python25\254\lib\encodings\utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x93 in position 5: unexpected code byte
答案 0 :(得分:38)
好问题。编码问题很棘手。让我们从“我有一个字符串开始。” Python 2中的字符串不是真正的“字符串”,它们是字节数组。所以你的字符串,它来自哪里,它是什么编码?您的示例在文字中显示了引号,我甚至不确定您是如何做到的。我尝试将其粘贴到Python解释器中,或者使用Option- [在OS X上键入它,但它没有通过。
看看你的第二个例子,你有一个十六进制93的字符。那不能是 UTF-8 ,因为在UTF-8中,任何高于127的字节都是多字节的一部分序列。所以我猜它应该是Latin-1。问题是,x93不是Latin-1字符集中的字符。 Latin-1中从x7f到x9f的这个“无效”范围被认为是非法的。但是,微软看到了未使用的范围,并决定在那里加上“曲线引号”。在这样做的过程中,他们创建了一个名为“windows-1252”的类似编码,就像Latin-1一样,其中包含无效范围的内容。
所以,我们假设它是 windows-1252 。现在怎么办? String.decode将字节转换为Unicode,这就是你想要的。你的第二个例子是在正确的轨道上,但它失败了,因为字符串不是UTF-8。尝试:
>>> uni = 'foo \x93bar bar\x94 weasel'.decode("windows-1252")
u'foo \u201cbar bar\u201d weasel'
>>> print uni
foo “bar bar” weasel
>>> type(uni)
<type 'unicode'>
这是正确的,因为打开卷曲引用是Unicode U + 201C。现在您已经拥有了Unicode,您可以使用您选择的任何编码将其序列化为字节(如果您需要通过网络传递它),或者如果它保留在Python中,则将其保留为Unicode。如果要转换为UTF-8,请使用反对函数string.encode。
>>> uni.encode("utf-8")
'foo \xe2\x80\x9cbar bar \xe2\x80\x9d weasel'
Curly引号需要3个字节才能以UTF-8编码。你可以使用UTF-16,它们只有两个字节。但是,您不能编码为ASCII或Latin-1,因为它们没有卷曲引号。
答案 1 :(得分:4)
修改即可。看起来您的字符串的编码方式使“
(LEFT DOUBLE QUOTATION MARK)变为\x93
,而”
(右双引号)变为\x94
。有许多具有这种映射的代码页,CP1250就是其中之一,所以你可以使用它:
s = s.decode('cp1250')
对于将“
映射到\x93
的所有代码页,请参阅here(所有这些代码页也将”
映射到\x94
,可以对其进行验证{{ 3}})。