Python UTF8 字符串困惑
我在这个问题上纠结了很久,读了很多文章,但问题还是不太清楚。我在数据库里存了一些字符串,想象一下如下的情况:
x = '\xd0\xa4'
y = '\x92'
在Python的命令行界面,我得到了以下结果:
print x
Ф
print y
?
这正是我想看到的结果。然而接下来出现了:
print unicode(x, 'utf8')
Ф
但不是这个:
unicode(y, 'utf8')
UnicodeDecodeError: 'utf8' codec can't decode byte 0x92 in position 0: unexpected code byte
我感觉我们的字符串可能被搞乱了,因为Django试图把它们转换成unicode格式,但我现在只是猜测。任何见解或解决方法都非常感谢。
更新:当我查看数据库中包含'\x92'值的那一行时,我看到这个字符是’。就是一个撇号。我是用Unicode UTF-8编码查看数据库内容的。
5 个回答
我原以为除了ASCII字符集以外的任何Unicode字符在UTF-8中都需要用多个字节来表示。你的y
作为每个字符用一个字节的字符串是合理的,但作为UTF-8字符串就不太对了。因为这个单字节的值超出了0x00到0x7F的ASCII范围,所以在转换成“真正的”Unicode字符时,编码器会期待有一个或多个额外的字节。
不过,我对Python的了解没有以前那么深了,所以对这个回答不是很有信心。
编辑 我觉得hops的回答更好。
\x92
不是一个有效的 UTF-8 编码字符。
你可能没有注意到这一点,因为你在使用简单的(非 Unicode)字符串作为 x
和 y
,直到你尝试将它们解码成 Unicode 字符串。当你打印它们时,它们就会直接显示在终端上,终端会根据它的编码设置来解释这些字节。
在 unicode()
函数中有一个第三个参数,可以告诉 Python 在遇到编码(解码)错误时该怎么做:
>>> unicode('\x92', 'utf8', 'replace')
u'\ufffd'
>>> print _
�
看起来你有个拼写错误;应该是 x = '\xd0\xa4'
。如果你能把你实际运行的代码和输出结果复制粘贴过来,会帮助很多。
"\x92" 不是一个有效的 UTF-8 字符串。这就是你收到异常的原因。
更让人困惑的是,为什么 print y
输出了 ?
。你所说的“Python 控制台”指的是什么呢?看起来它在“替换”模式下运行,把某些字符替换成了“?”……你确定它只是一个普通的“?”而不是一个黑色菱形里的白色“?”吗?你为什么说“?”正是你期待看到的呢?
更新:你现在说:“当我查看数据库中包含 '\x92' 值的那一行时,我看到这个字符是 ’。一个撇号。我是用 Unicode UTF-8 编码查看数据库内容的。”
那不是撇号。看起来那段数据是用 cp125X(也就是 windows-125X)编码的。用 cp1252(常见的编码)来说明:
IDLE 2.6.4
>>> import unicodedata
>>> uc = '\x92'.decode('cp1252')
>>> print repr(uc)
u'\u2019'
>>> print uc
’
>>> unicodedata.name(uc)
'RIGHT SINGLE QUOTATION MARK'
>>>
与其说“用 Unicode UTF-8 编码查看数据库内容”(这是什么意思呢),不如写一小段 Python 代码来提取出有问题的字符串,然后执行 print repr(bad_string)
。把你运行的代码和 repr() 的输出结果都给我们看看。还请告诉我们你使用的 Python 版本、平台(Windows 还是基于 Unix 的),以及你用的数据库软件版本。还有与问题相关的 CREATE TABLE 语句部分。