使用python时经常会遇到字符串编解码的问题,这里分享2.4版本中一些与之相关的经验。
1)unicode和UTF8、gbk、UTF16的区别。
简单来说,unicode是一种编码标准,UTF8,gbk,UTF16都是具体的编码,可以认为是unicode的实现,通常用于数据的存储和传输。例如”中“的unicode编码是4e2d, gbk编码是d6d0。utf8编码是E4 B8 AD。
2)python里的encode和decode
假设,a = u"中" (u表示a是unicode字符),python里encode通常是将unicode形式的字符编码成具体编码(例如gbk)。反之,decode是将具体的编码转化成unicode。
例如:
aGbk = a.encode("gbk") aGbk保存"中"的gbk编码结果。
aUtf8 = a.encode("utf8") aUtf8保存"中"的utf8的编码结果
aUnicode = aGbk.decode("gbk") 使用gbk将aGbk解码成unicode。此时aUnicode与a相等
aUnicode = aUtf8.decode("utf8") 使用utf8将aUtf8解码成unicode。此时aUnicode与a相等
3) unicode操作符
有时会见到 b= unicode("中","gbk")这种表达式。实际上,unicode和decode的作用等效。
例如这里 b实际上与 "中".decode("gbk")的结果相等。
4)常见错误1:UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data
这种错误通常发生在尝试将字符串解码成unicode时。例如下面的表示式执行时就会触发上述错误。
"中".decode("utf8")。 可能大家会问,为什么"中".decode("gbk")就没问题呢?"中"不是可以编码成utf8么。这里涉及到一个内码概念。操作系统默认会使用一种编码(内码)来解释文件。例如,中文XP和Win7都会采用gbk作为系统内部编码。大家使用记事本保存文件时,由于系统内码是gbk(实际上可能是GB18030,也可能是GB2312以及gbk),该文件实际会被保存为gbk格式。
从这个角度来看,"中".decode("utf8")会出现错误就正常了,因为"中"本身是以gbk的形式在内存中存储的,使用utf8去解码gbk字符串当然有可能会错了。
当然,如果恰好某个gbk编码的字符落在utf8的解释范围,则上述错误也可能不会出现。
例如"一".decode("gbk")的结果是4e00,而"一".decode("utf8")的结果是04bb.
"一".decode("gbk")的结果可以用print正常显示,而print "一".decode("utf8")的结果则抛出了另外一个错误:
UnicodeEncodeError: 'gbk' codec can't encode character u'\u04bb' in position 0 illegal multibyte sequence
5)常见错误2:UnicodeEncodeError: 'gbk' codec can't encode character u'\u04bb' in position 0 illegal multibyte sequence
这种错误通常发生在尝试将unicode字符串编码成具体编码的字符串时。例如上面的 print "一".decode("utf8").
"一".decode("utf8")的结果是unicode字符串,而print默认是以gbk来编码参数并显示的。因此,上述函数调用实际是想以
gbk来编码unicode字符串。由于"一".decode("utf8")生成的unicode结果不在gbk的解释范围,因此会出现unicode编码错误。
6)关于u的一些误区
通常来说,a = u"中" 是将a定义成unicode字符串,那么 a.encode("gbk")通常应该能得到正确结果,例如在控制台上这样做没问题。
现在我们假设一个文件的内容如下:
a = u"中"
print a.encode("gbk")
在某些IDE中执行该文件时,发现print a.encode("gbk")语句执行会产生如下错误:UnicodeEncodeError: 'gbk' codec can't encode character u'\xd6' in position 0: illegal multibyte sequence
,这个错误很熟悉吧,使用gbk编码unicode时的错误。那这又是什么原因呢?
原因在于python环境在导入python文件并执行时,会先查看文件头有没有编码声明,例如#encoding:gbk 。如果发现声明,会将文件中的字符串都先解释成
unicode的形式。例如将a先用gbk解码成d6d0后保存,之后执行a.encode("gbk")时,由于a已经是unicode的形式,所以编码不会出现错误;
如果文件头没有编码声明,则将直接使用gbk解码d6,由于d6不在gbk的解释范围,自然会出现错误了。
因此,为了避免这种类型的错误,别忘了在文件头加上编码声明。这样,文件中的u字符串都会已该编码的形式保存。
并且文件在导入并执行时,python解释器会先将字符串使用指定的编码形式解码成unicode。
7)如何判断一个字符串是ansii字符串还是unicode字符串?
要注意的是,无论是gbk,还是utf8,utf16,都是ascii类型的字符串,只有unicode的编码形式的字符串才是unicode类型字符串(有点绕)。
假设 a = "中", 则使用type函数来获取该字符串的类型时结果是<type 'str'>,
b = u"中", type(b)的结果是<type 'unicode'>。
那么,如何动态判断一个字符串的类型呢?可以使用如下方法:
if type(a) == str:
dosomething() #a是ascii类型
if type(a) == unicode:
dosometing2() #a是unicode类型
8)对字符串的操作最好都通过unicode来进行。例如字符串比较时,将参数都解码成unicode后再比较。正则表达式的模式和参数也最好都采用unicode的形式;读写文件时也最好使用unicode字符串来进行。
1)unicode和UTF8、gbk、UTF16的区别。
简单来说,unicode是一种编码标准,UTF8,gbk,UTF16都是具体的编码,可以认为是unicode的实现,通常用于数据的存储和传输。例如”中“的unicode编码是4e2d, gbk编码是d6d0。utf8编码是E4 B8 AD。
2)python里的encode和decode
假设,a = u"中" (u表示a是unicode字符),python里encode通常是将unicode形式的字符编码成具体编码(例如gbk)。反之,decode是将具体的编码转化成unicode。
例如:
aGbk = a.encode("gbk") aGbk保存"中"的gbk编码结果。
aUtf8 = a.encode("utf8") aUtf8保存"中"的utf8的编码结果
aUnicode = aGbk.decode("gbk") 使用gbk将aGbk解码成unicode。此时aUnicode与a相等
aUnicode = aUtf8.decode("utf8") 使用utf8将aUtf8解码成unicode。此时aUnicode与a相等
3) unicode操作符
有时会见到 b= unicode("中","gbk")这种表达式。实际上,unicode和decode的作用等效。
例如这里 b实际上与 "中".decode("gbk")的结果相等。
4)常见错误1:UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data
这种错误通常发生在尝试将字符串解码成unicode时。例如下面的表示式执行时就会触发上述错误。
"中".decode("utf8")。 可能大家会问,为什么"中".decode("gbk")就没问题呢?"中"不是可以编码成utf8么。这里涉及到一个内码概念。操作系统默认会使用一种编码(内码)来解释文件。例如,中文XP和Win7都会采用gbk作为系统内部编码。大家使用记事本保存文件时,由于系统内码是gbk(实际上可能是GB18030,也可能是GB2312以及gbk),该文件实际会被保存为gbk格式。
从这个角度来看,"中".decode("utf8")会出现错误就正常了,因为"中"本身是以gbk的形式在内存中存储的,使用utf8去解码gbk字符串当然有可能会错了。
当然,如果恰好某个gbk编码的字符落在utf8的解释范围,则上述错误也可能不会出现。
例如"一".decode("gbk")的结果是4e00,而"一".decode("utf8")的结果是04bb.
"一".decode("gbk")的结果可以用print正常显示,而print "一".decode("utf8")的结果则抛出了另外一个错误:
UnicodeEncodeError: 'gbk' codec can't encode character u'\u04bb' in position 0 illegal multibyte sequence
5)常见错误2:UnicodeEncodeError: 'gbk' codec can't encode character u'\u04bb' in position 0 illegal multibyte sequence
这种错误通常发生在尝试将unicode字符串编码成具体编码的字符串时。例如上面的 print "一".decode("utf8").
"一".decode("utf8")的结果是unicode字符串,而print默认是以gbk来编码参数并显示的。因此,上述函数调用实际是想以
gbk来编码unicode字符串。由于"一".decode("utf8")生成的unicode结果不在gbk的解释范围,因此会出现unicode编码错误。
6)关于u的一些误区
通常来说,a = u"中" 是将a定义成unicode字符串,那么 a.encode("gbk")通常应该能得到正确结果,例如在控制台上这样做没问题。
现在我们假设一个文件的内容如下:
a = u"中"
print a.encode("gbk")
在某些IDE中执行该文件时,发现print a.encode("gbk")语句执行会产生如下错误:UnicodeEncodeError: 'gbk' codec can't encode character u'\xd6' in position 0: illegal multibyte sequence
,这个错误很熟悉吧,使用gbk编码unicode时的错误。那这又是什么原因呢?
原因在于python环境在导入python文件并执行时,会先查看文件头有没有编码声明,例如#encoding:gbk 。如果发现声明,会将文件中的字符串都先解释成
unicode的形式。例如将a先用gbk解码成d6d0后保存,之后执行a.encode("gbk")时,由于a已经是unicode的形式,所以编码不会出现错误;
如果文件头没有编码声明,则将直接使用gbk解码d6,由于d6不在gbk的解释范围,自然会出现错误了。
因此,为了避免这种类型的错误,别忘了在文件头加上编码声明。这样,文件中的u字符串都会已该编码的形式保存。
并且文件在导入并执行时,python解释器会先将字符串使用指定的编码形式解码成unicode。
7)如何判断一个字符串是ansii字符串还是unicode字符串?
要注意的是,无论是gbk,还是utf8,utf16,都是ascii类型的字符串,只有unicode的编码形式的字符串才是unicode类型字符串(有点绕)。
假设 a = "中", 则使用type函数来获取该字符串的类型时结果是<type 'str'>,
b = u"中", type(b)的结果是<type 'unicode'>。
那么,如何动态判断一个字符串的类型呢?可以使用如下方法:
if type(a) == str:
dosomething() #a是ascii类型
if type(a) == unicode:
dosometing2() #a是unicode类型
8)对字符串的操作最好都通过unicode来进行。例如字符串比较时,将参数都解码成unicode后再比较。正则表达式的模式和参数也最好都采用unicode的形式;读写文件时也最好使用unicode字符串来进行。