Python 字符编码

许多博客写得垃圾,自己都不明白,还在那里误人子弟,只给解决方法而不说明原因的博客都他妈的是流氓。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

>>> u'中文测试'.encode('unicode-escape')

'\\u4e2d\\u6587\\u6d4b\\u8bd5'

unicode-escape到unicode的转换方法:unicodeescapestr.decode('unicode-escape'),示例:

1

2

>>> '\\u4e2d\\u6587\\u6d4b\\u8bd5'.decode('unicode-escape')

u'\u4e2d\u6587\u6d4b\u8bd5'

需要注意的是如果使用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 SequenceMeaningNotes
\newlineBackslash and newline ignored 
\\Backslash (\) 
\'Single quote (') 
\"Double quote (") 
\aASCII Bell (BEL) 
\bASCII Backspace (BS) 
\fASCII Formfeed (FF) 
\nASCII Linefeed (LF) 
\rASCII Carriage Return (CR) 
\tASCII Horizontal Tab (TAB) 
\vASCII Vertical Tab (VT) 
\oooCharacter with octal value ooo(1,3)
\xhhCharacter with hex value hh(2,3)

Escape sequences only recognized in string literals are:

Escape SequenceMeaningNotes
\N{name}Character named name in the Unicode database(4)
\uxxxxCharacter with 16-bit hex value xxxx(5)
\UxxxxxxxxCharacter 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

>>> '中文测试'.encode('string-escape')

'\\xe4\\xb8\\xad\\xe6\\x96\\x87\\xe6\\xb5\\x8b\\xe8\\xaf\\x95'

>>> print '\\xe4\\xb8\\xad\\xe6\\x96\\x87\\xe6\\xb5\\x8b\\xe8\\xaf\\x95'

\xe4\xb8\xad\xe6\x96\x87\xe6\xb5\x8b\xe8\xaf\x95

string-escape到utf-8的转换方法:strescapestr.decode('string-escape'),示例:

1

2

3

4

>>>'\\xe4\\xb8\\xad\\xe6\\x96\\x87\\xe6\\xb5\\x8b\\xe8\\xaf\\x95'.decode('string-escape')

'\xe4\xb8\xad\xe6\x96\x87\xe6\xb5\x8b\xe8\xaf\x95’

>>> print '\xe4\xb8\xad\xe6\x96\x87\xe6\xb5\x8b\xe8\xaf\x95'

中文测试

 

参考资料

Python编程-字符串的编码转换、存储及乱码问题

python 3.3.3 字面量,正则,反斜杠和原始字符串

python官方文档

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值