[关闭]
@zwenqiang 2015-06-05T23:47:25.000000Z 字数 1785 阅读 11764

Python2中的编码错误

python开发

python2中常出现的编码问题

  1. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 4: ordinal not in range(128)

对中文字符串解码出错
虽然可以在代码头部加入以下代码解决

  1. import sys
  2. import sys
  3. reload(sys)
  4. sys.setdefaultencoding("utf-8")

但是这种方式已经不推荐使用了[详细阅读]。所以推荐使用以下方式
xxx.decode("utf-8")
或者在你需要使用中文的地方前面加上u.Python2默认的字符串编码是str

这种错误通常发生在以某种编码("ascii")解码一个str类型的字符串时.因为编码映射仅仅只能支持一部分str类型的字符串到unicode字符串, 一个非法的str类型的序列将会导致编码decode()失败。 [详细阅读]

str字符串\x81就不能转化为unicode对应的字符串

  1. >>> "\x81".decode("utf-8")
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
  5. return codecs.utf_8_decode(input, errors, True)
  6. UnicodeDecodeError: 'utf8' codec can't decode byte 0x81 in position 0: invalid start byte

另一种情况的解码错误

自相矛盾的是,UnicodeDecodeError也可能发生在编码__encoding__时。
原因是编码函数encode()通常情况下需要一个unicode类型的字符串作为参数。但是实际传过来的是一个str类型的参数。encode()函数将这个参数向上转换"up-convert"为unicode类型,然后再将转化为他们自己的编码。这也会出现这样的向上转换"up-convertion"的时候,系统默认选择一个ascii解码器, 解码器中没有这个str类型的unicode编码, 。因此这是在一个编码器encoder中出现解码失败的情况。

str类型的\xd0\x91在encode()时就会出现UnicodeDecodeError错误

  1. >>> "\xd0\x91".encode("utf-8")
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)

在这个过程中发生了两件事情。首先\xd0\x91是python默认的str类型的字符串,而编码encode需要一个unicode类型的字符串,所以在编码encode之前,先转化为unicode,而执行的是"\xd0\x91".decode("ascii"), 所以会出现上面的错误。

  1. >>> "\xd0\x91".decode("ascii")
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)
  5. >>> # 而如果使用utf-8 转码的话就可以正常执行
  6. >>> "\xd0\x91".decode("utf-8")
  7. u'\u0411'

总结

所以出现上面的UnicodeDecodeError错误时,可以不使用系统的ascii编码解码,自己使用utf-8解码就可以解决问题,即xx.decode("utf-8")。但是如果str类型的字符串非常特殊,如第一种例子中的\x81的话就直接无法转码了。所以最好的方法还是将一个字符串定义为unicode类型。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注