Python编码问题
2015-07-10 20:41
901 查看
Python编码问题总结
下面的文章和编码具体解释总结了常见字符编码后,这篇文章会对python中常见的编码问题进行分析和总结。因为python3.x版本号和python2.x版本号在字符编码方面有非常大差异,所以本文都是以Python2.7.5来分析2.x版本号中的字符编码问题。
1.Python编码基础
1.1 str和unicode
python中有两种数据模型来支持字符串这样的数据类型,str和unicode,它们的基类都是basestring。比方
s = "中文"就是str类型的字符串,而
u=u"中文"就是一个unicode类型的字符串。unicode是由str类型的字符串解码后得到。unicode也能够编码成str类型。即
str --> decode -->unicode unicode --> encode --> str
严格来说,str或许应该叫做字节串,由于对于UTF-8编码的str类型"中文",使用len()函数得到的结果是6,由于UTF-8编码的str类型[code]“中文”实际是
"\xe4\xb8\xad\xe6\x96\x87"。
而对于unicode类型u“中文”(实际是
u"\u4e2d\u6587"),使用len()函数得到结果是2.[/code]
1.2 头部编码声明
在python源码文件里假设实用到非ascii字符,比方中文,那么须要在源码文件头部声明源码字符编码,格式例如以下:#-*- coding: utf-8 -*-
这个格式看起比較复杂,事实上python仅仅检查#、coding,编码等字符串,能够简写成#coding:utf-8,甚至还能够写成#coding:u8。
2.Python2.x常见编码问题
2.1 头部编码声明和文件编码问题
文件头部编码声明决定了python解析源代码中的str的编码选择方式,比方头部声明的是utf-8编码,则代码中s="中文"python就会依照utf-8编码格式来解析,通过
repr(s)能够看到字符编码是
"\xe4\xb8\xad\xe6\x96\x87"。假设头部声明的编码是gbk编码,则python会对s採用gbk编码解析。结果是
"\xd6\xd0\xce\xc4"。
须要注意的是,文件本身的编码要跟文件头部声明编码一致,不然就会出现故障。
文件本身的编码在Linux以下能够在vim下用命令
set fenc来查看。
假设文件本身编码是gbk。而源代码文件头部声明的编码是utf-8,这样假设源代码中有中文就会有问题了,由于本身中文str存储是依照gbk编码来的。而python在解析str的时候又以为是utf-8编码。这样就会报
SyntaxError: (unicode error) 'utf8' codec can't decode byte错误。
2.2 默认编码问题
以下看个python默认编码导致的问题:#coding: utf-8 u = u"中文" print repr(u) # u'\u4e2d\u6587' s = "中文" print repr(s) # '\xe4\xb8\xad\xe6\x96\x87' u2 = s.decode("utf-8") print repr(u2) # u'\u4e2d\u6587' #s2 = u.decode("utf-8") #编码错误 #u2 = s.encode("utf-8") #解码错误
注意实例中凝视掉的2行代码,对于unicode最好不要直接调用decode。str最好不要直接调用encode方法。由于假设是直接调用。则相当于[code]u.encode(default_encoding).decode("utf-8")。default_encoding是python的unicode实现中用的默认编码,即
sys.getdefaultencoding()得到的编码,假设你没有设置过。那么默认编码就是ascii,假设你的unicode本身超出了ascii编码范围就会报错。同理,假设对str直接调用encode方法,那么默认会先对str进行解码。即s.decode(default_encoding).encode("utf-8"),假设str本身是中文,而default_encoding是ascii的话。解码就会出错,从而导致上面这两行会分别报
UnicodeEncodeError: 'ascii' codec can't encode characters in position...错误和
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position...错误。[/code]
上面样例中凝视掉的两行代码假设运行就会报错,当然,假设本身str或者unicode都在ascii编码范围。就没有问题。比方
s = "abc"; s.encode("utf-8")就不会有问题。语句运行后会返回一个跟s的id不同的str。
那假设要解决实例1中的问题,有两种方法,其一是明白指定编码,例如以下所看到的:
#coding: utf-8 u = u"中文" print repr(u) # u'\u4e2d\u6587' s = "中文" print repr(s) # '\xe4\xb8\xad\xe6\x96\x87' u2 = s.decode("utf-8") print repr(u2) # u'\u4e2d\u6587' s2 = u.encode("utf-8").decode("utf-8") # OK u2 = s.decode("utf8").encode("utf-8") # OK
另外一种方法就是更改python的默认编码为文件编码格式,例如以下所看到的(这里仅仅所以要reload sys模块。是由于python初始化后删除了setdefaultencoding方法):
#coding:utf-8 import sys reload(sys) sys.setdefaultencoding("utf-8") #更改默认编码为utf-8 u = u"中文" print repr(u) # u'\u4e2d\u6587' s = "中文" print repr(s) # '\xe4\xb8\xad\xe6\x96\x87' u2 = s.decode("utf-8") print repr(u2) # u'\u4e2d\u6587' s2 = u.decode("utf-8") u2 = s.encode("utf-8")
2.3读写文件编码
採用python的open()方法打开文件时,read()读取的是str,编码就是文件本身的编码。而调用write()写文件时,假设參数是unicode,则须要用指定编码encode,假设write()參数是unicode并且没有指定编码,则会採用python默认编码encode后再写入。#coding:utf-8 f = open("testfile") s = f.read() f.close() print type(s) # <type 'str'> u = s.decode("utf-8") #testfile是utf-8编码 f = open("testfile", "w") f.write(u.encode("gbk")) #以gbk编码写入,testfile为gbk编码 f.close()
此外,python的codecs模块提供了一个open()方法。能够指定编码打开文件。使用这种方法打开文件读取返回是unicode。
写入时,假设write參数是unicode,则使用打开文件时的编码写入,假设是str,则先使用默认编码解码成unicode后再以打开文件的编码写入(这里须要注意假设str是中文,而默认编码sys.getdefaultencoding()是ascii的话会报解码错误)。
#coding:gbk import codecs f = codecs.open('testfile', encoding='utf-8') u = f.read() f.close() print type(u) # <type 'unicode'> f = codecs.open('testfile', 'a', encoding='utf-8') f.write(u) #写入unicode # 写入gbk编码的str,自己主动进行解码编码操作 s = '汉' print repr(s) # '\xba\xba' # 这里会先将GBK编码的str解码为unicode再编码为UTF-8写入 #f.write(s) #默认编码为ascii时。这会报解码错误。 f.close()
3.參考资料
python字符编码详细解释相关文章推荐
- python中@property的使用
- Install Deepdream(Caffe-python) on Mac OS X
- 邀请码生成析
- python并行处理任务时 该用多进程?还是该用多线程?
- [Python] Python 之 __new__() 方法与实例化
- 说说Python程序的执行过程
- python logging
- Python中and和or
- python学习笔记——Tkinter GUI编程——简介
- 对python中的字典进行排序
- Python实现分割文件及合并文件的方法
- python 编码问题——字符编码
- python基础课程_学习笔记26:编程的乐趣
- Python学习笔记5
- Python写入数据到MP3文件中的方法
- 模拟登陆之填入cookie【python】
- 【python】多进程多线程
- Python将阿拉伯数字转换为罗马数字的方法
- Python自动登录126邮箱的方法
- Python获取邮件地址的方法