许多博客写得垃圾,自己都不明白,还在那里误人子弟,只给解决方法而不说明原因的博客都他妈的是流氓。python字符编码下面一篇博客堪称经典,看这一篇足够解决。
【总结】Python 2.x中常见字符编码和解码方面的错误及其解决办法
下面是我自己的记录,仅作自己记忆,不必看。
1.python编码转换
首先明确encode和decode的含义。
encode的使用对象是unicode,即u.encode('utf8')表示将unicode类型编码成utf8的格式,u必须是unicode或者能解码成unicode
decode的使用对象是指定编码,即s.decode('gbk')表示将s按照gbk格式解码成unicode,前提是s必须是以gbk格式编码的,否则一定会报错,报错内容类似于:
UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence
Python中两种编码转换需要unicode做媒介,比如print s, s类型为str,linux系统下系统默认编码为utf8编码,s在输出前就应该编码为utf8。如果s为gbk编码就应该这样输出。print s.decode('gbk').encode('utf8')才能输出中文。
2.chardet
chardet 可以检测内容的编码,但是不是很准确
import chardet
content=open('file','r').readline()
fencoding=chardet.detect(content)
print fencoding
然后
content=content.decode(fencoding['encoding']).encode("utf-8")
可以将content转为指定的编码,如utf-8
3.unicode-escape
实际上,在将unicode存储到文本的过程中,还有一种存储方式,不需要将unicode转换为实际的文本存储字符集,而是将unicode的内存编码值进行存储,读取文件的时候再反向转换回来,是采用:unicode-escape的转换方式。
unicode到unicode-escape转换方法:unicodestr.encode('unicode-escape'),示例:
1 2 |
|
unicode-escape到unicode的转换方法:unicodeescapestr.decode('unicode-escape'),示例:
1 2 |
|
需要注意的是如果使用unicodeescapestr.decode('unicode-escape'),那么unicodeescapestr中的字符不能有类似\N或\u这样的两个字符,
>>> str="asdfa\Nsdf"
>>> str=str.decode('unicode-escape')
上面的代码会报类似于“UnicodeDecodeError: 'unicodeescape' codec can't decode bytes in position 5-6: malformed \N character escape”这样的错误,意思是使用python内部unicodeescape字符解码器不能按\N进行解码。\表示转义,即按照其后跟的字符进行转义,根据下面的表格我们可以知道\N后面必须是符合Character named name in the Unicode database的字符,如果其后面的字符不符合规则,那么unicodeescape解码器就无法按Character named name in the Unicode database正常解析转义字符\N后面的字符,同理\u和\U后面分别需要跟着16bit的16进制字符串和32bit16进制字符串,unicodeescape解码器才能正常解析,否则就会报错。
Escape Sequence | Meaning | Notes |
---|---|---|
\newline | Backslash and newline ignored | |
\\ | Backslash (\ ) | |
\' | Single quote (' ) | |
\" | Double quote (" ) | |
\a | ASCII Bell (BEL) | |
\b | ASCII Backspace (BS) | |
\f | ASCII Formfeed (FF) | |
\n | ASCII Linefeed (LF) | |
\r | ASCII Carriage Return (CR) | |
\t | ASCII Horizontal Tab (TAB) | |
\v | ASCII Vertical Tab (VT) | |
\ooo | Character with octal value ooo | (1,3) |
\xhh | Character with hex value hh | (2,3) |
Escape sequences only recognized in string literals are:
Escape Sequence | Meaning | Notes |
---|---|---|
\N{name} | Character named name in the Unicode database | (4) |
\uxxxx | Character with 16-bit hex value xxxx | (5) |
\Uxxxxxxxx | Character with 32-bit hex value xxxxxxxx | (6) |
这样替换字符串content中可能出现的\N可以解决问题,但是需要将\N替换成\\N,请注意python正则匹配\需要用三个\\\来匹配,小于三个的话等于没有,直接匹配\\或\后面的字符
content=re.sub("\\\N", "\\\\\N", content) #如果用decode('unicode-escape'),那么content不能存在\N或\U或\u这种转义符,
content=re.sub("\\\u", "\\\\\u", content) #如果存在这些符号,后面跟的内容必须是正确的转义规则所指的内容
content=re.sub("\\\U", "\\\\\U", content) #如果使用sub("\N", "\\N", content),并不仅仅匹配\N,还会匹配所有的N
content=content.decode('unicode-escape') #这样就能避免解析失败而报错,但是原始字符串中的\N会替换为\\N
4.string-escape
对于utf-8编码的字符串,在存储的时候,通常是直接存储,而实际上也还有一种存储utf-8编码值的方法,即:string-escape。
utf-8到string-escape的转换方法:utf8str.encode('string-escape'),示例:
1 2 3 4 |
|
string-escape到utf-8的转换方法:strescapestr.decode('string-escape'),示例:
1 2 3 4 |
|
参考资料