【学习笔记】python 编码相关问题总结

关于python的编码,尤其是中文编码,会给新手带来很大的困扰。我以前遇到问题时搜索一下,虽然磕磕碰碰能解决并且顺利输出,但是背后的逻辑并未从根本上搞懂。

现在此仔细的整理一下,希望能让有同样疑惑的朋友有所收获。如有错误,也希望大家批评指正。

另外,这里针对的是python 2.7。python 3又有一些不同。

 

1、简单说一下字符编码

字符编码简单来讲就是转意,扩充基本字符的含义。

 

2、python字符串的类型

python字符串的类型有两种,一种是str,一种是unicode。这两者都是继承自抽象类basestring。

str是默认的字符串类型,本质上是8-bit string。构造方式如下

 

#默认的字符串就是str类型
s = '123'
print type(s)
#输出 <type 'str'>

#使用构造函数
s = str(123)
print type(s)
#输出 <type 'str'>


str类型的默认编码是ascii,因此默认情况下str不能表示中文,或者说在默认情况下py文件里都不能写中文

 

 

str1='中国'

#报错
#SyntaxError: Non-ASCII character '\xe4' in file C:\Users\Administrator\Desktop\1.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

对此的解决方法是更改str类型的编码集,使用utf-8。这需要在文件头进行声明(声明方式有多种,这里举一例)

 

 

# -*- coding: UTF-8 -*-

str1='中国'
print str1
#输出 中国

 

这里再介绍repr函数,以深化理解。repr()作用是将一个对象转成字符串显示,因此repr('中国')会显示真正存储的字符,而无视编码规则

 

# -*- coding: UTF-8 -*-

str1='中国'
print repr(str1)
#输出 '\xe4\xb8\xad\xe5\x9b\xbd'

 

 

 

下面介绍unicode类型。

unicode对象是无编码的字符串,或者说使用的是一套通用的字符编码集。python的unicode对象和真正的unicode编码其实不尽相同,但是我们不用考虑。

作为编码方式的unicode,中文叫万国码,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。unicode只是一种笼统的规范,具体的实现方式有utf-8、utf-16等。中文常用的就是utf-8编码,即8-bit Unicode Transformation Format,是可变长度的字符编码

unicode的构造方式如下

 

#构造函数
u = unicode(123)
print type(u)
#输出 <type 'unicode'>

#或者用u+字符串方式
u = u'123'
print type(u)
#输出 <type 'unicode'>


unicode的作用是统一各种编码,其通用性可以避免不同编码方式会带来的错误。python包如json和urllib2,其请求的发送或返回值都是unicode编码。

 

unicode输出中文的方式就是重新编码,方法如下

 

# -*- coding: UTF-8 -*-

#使用encode函数进行编码,编码集为utf-8
u = u'中国'
print u.encode('utf-8')
#输出 中国

#如果不使用,则报错
#这里尽管str类型的编码被改为了utf-8,对于print函数来说仍是ascii
print u
#UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)


再介绍一种unicode输出中文的方式:统一指定unicode的编码

 

 

 

 

# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )

u = u'中国'
print u
#输出 中国

 

 

 

 

 

3、decode和encode

python提供了解码和编码的函数decode和encode,其逻辑如下:

str——经过str.decode()——得到解码的unicode对象

unicode——经过unicode.encode()——得到编码的str对象

 

# -*- coding: UTF-8 -*-

s = '123'
print type(s)
#输出 <type 'str'>

#根据s编码方式选择解码方式
u = s.decode('utf-8')
print type(u)
#输出 <type 'unicode'>
s = u.encode('utf-8')print type(s)
#输出 <type 'str'>


4、最后介绍另一个工具chardet

 

使用chardet包可以查看str类型的编码方式。可以通过easy_install下载。查看方式如下

 

# -*- coding: UTF-8 -*-

import chardet

s = '中国'
print chardet.detect(s)
#{'confidence': 0.7525, 'encoding': 'utf-8'}
#注意到这里有'confidence',说明了chardet.detect是通过字符编码推测得出结论的

s = '123'
print chardet.detect(s)
#{'confidence': 1.0, 'encoding': 'ascii'}
#尽管指定了str编码为utf-8,但是由于utf-8的0-127与ascii相同,这里故无法察觉

s = '中国'.decode('utf-8').encode('gb2312')
print chardet.detect(s)
#{'confidence': 0.7679697235616183, 'encoding': 'IBM855'}
#指定了不同的编码方式,可以识别出来。此外这说明了gb2312和IBM855之间具有联系

s = '123'.decode('utf-8').encode('gb2312')
print chardet.detect(s)
#{'confidence': 1.0, 'encoding': 'ascii'}
#这里与上面情况2原理相同

 

 

5、关于读文件

一般来说同一个文件的编码应该是同一套的,对于纯utf-8、纯gbk2312编码的文件,直接使用open()即可。注意open()函数返回的每一行都是str类型的对象。

如果你想用不同的编码处理文件,按照前文所述,可以对每一行使用decode+encode的方法,也可以引用codecs包,在读文件时使用 codecs.open(filename,'utf-8') 等方法统一解码,此时返回的每一行都是unicode对象,再分别编码即可。(这就不需要上代码例子了)

需要注意的是,windows的txt文件可能会使用一种叫ANSI的编码方式。对于这种方式编码的文件,其每一行用chardet检测都可能显示出不同的编码(以gb2312/gbk为主)。不要以为这就是混合编码,实际上简体中文的windows系统的ANSI编码就是gbk编码,一般来说使用gbk解码即可。如果中途遇到问题,只需要另存为TXT文件,右下角改变编码方式为UTF-8等即可。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值