Python-编码那趟浑水

图片 1

Python编码错误及消除办法

字符串是Python中最常用的数据类型,而且不少时候会用一些不属于ascii字符集的字符,那是就能抛出UnicodeDecodeError:ascii
codec can’t decode byte 0xc肆 in position 10:oridinal not
range(12八)分外。这种特别在python中很轻松遭受,非常是在Python二.x中

字符串在Python3.x内部的代表是unicode编码,因而,在做编码转变时,经常要求以unicode作为转码的中档编码,即先将别的编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。但是在Python二.x中私下认可编码格式是ascii,正是说在未有一些名Python源码编码格式的气象下,源码中颇具字符都被默认为ascii码。也是因为这么些根本原因,在Python二.x中平时蒙受UnicodeDecodeError也许UnicodeEncodeError的不得了。

Unicode为了能够管理Unicode数据,同时合作Python某个内部模块,Python二.x中提供了Unicode这种数据类型,通过decode和encode方法可以将别的编码和unicode编码互相调换。

什么恒久地将暗许编码设置为utf-⑧呢?  有2种方法:

首先个措施<不推荐>: 编辑site.py, 修改setencoding()函数, 强制安装为
utf-8
其次个办法<推荐>: 扩展2个名字为 sitecustomize.py, 推荐存放的门路为
site-packages 目录下
sitecustomize.py 是在 site.py 被import 试行的, 因为
sys.setdefaultencoding() 是在 site.py 的尾声删除的, 所以, 能够在
sitecustomize.py 使用 sys.setdefaultencoding().
复制代码 代码如下:
import sys  
sys.setdefaultencoding(‘utf-8’)

既是 sitecustomize.py 能被电动加载,  所以除了设置编码外,
也能够安装有些别样的事物
字符串的编码
复制代码 代码如下:
s1=’中文’

像上边那样直接输入的字符串是依据代码文件的编码来拍卖的,假设是unicode编码,有以下三种情势:
复制代码 代码如下:
1 s1 = u’中文’
2 s2 = unicode(‘中文’,’gbk’)
3 s3 = s1.decode(‘gbk’)

unicode是叁个平放函数,第二个参数提醒源字符串的编码格式。
decode是其余字符串具备的不2秘诀,将字符串转变到unicode格式,参数提示源字符串的编码格式。
encode也是任何字符串具备的办法,将字符串转变到参数钦定的格式。

复制代码
代码如下: import os import codecs filenames=os.listdir(os.getcwd())
out=file(“name.txt”,”w”) for filename in fi…

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-八编码的str类型”中文”,使用len()函数获得的结果是陆,因为UTF-八编码的str类型“中文”实际是"\xe4\xb8\xad\xe6\x96\x87"。而对于unicode类型u“中文”(实际是u"\u4e2d\u6587"),使用len()函数获得结果是贰.

道理当然是那样的感到数据读取错误,笔者特将fp.write改成print,结果数据总体读取并呈现在指令调整台上了,证南宋码是一贯不难点的,仔细看了下特别新闻,貌似是因为编码难点:Unicode编码与ASCII编码的不相配,其实这么些Python脚本文件是由utf-八编码的,同时SQlite3数据仓库储存取的也是UTF-八格式,Python暗中认可情形编码通过上边包车型客车主意能够得到:

Python中编码规范

1.遵从PEP0二陆三原则,注脚编码格式(推荐)

在PEP 0二陆三 Defining Python Source Code
Encodings中提议了对Python编码难题的最主旨的消除办法:在Python源码文件中声称编码格式,最普及的证明格式如下:

#!/usr/bin/python
#! -*- encoding:utf-8 -*-

表示当前.py文件的字符串编码格式都以根据“utf-八”编码的,不是读取的文件是用“utf-8”编码读取的

二.应用 u’普通话’ 代替汉语(Python 2.x)

s1 = '中文'

s2 = u'中文'

Python中有以上二种表明字符串变量的不二法门,它们的机要的是编码格式的不如,其余s一的编码格式和Python头文件宣称的编码格式一致,而s2的编码格式则是unicode。假如你表明的字符串变量中带有非ascii字符,最佳使用s二的的宣示格式,那样你能够不须求推行decode,直接对字符串进行操作,能够幸免出现二个极其。

只顾:Python三中不存在 u’xx’的扬言格局。

三.Reset默许编码

Python中冒出那样多的编码难点的根本原因是Python
2x中的暗许编码是ascii,所以你能够透过以下的秘技修改默许的编码格式:

import sys
sys.setdefaultencoding('utf-8')

这种措施能够化解部分编码难点,可是还要也会引入大多别的标题,寸进尺退,提议不要采纳这种方法。

 

Python中选用不一致编码读写txt文件详解,

复制代码 代码如下:
import os
import codecs
filenames=os.listdir(os.getcwd())

out=file(“name.txt”,”w”)
for filename in filenames:
 out.write(filename.decode(“gb2312”).encode(“utf-8”))
out.close()

将试行文书的当前目录及文件名写入到name.txt文件中,以utf-八格式保存
假定运用ANSI编码保存,用如下代码写入就可以:
复制代码 代码如下:
out.write(filename)

展开文件并写入

引用codecs模块,对该模块近期不精晓。在此记录下方法,有空精通该模块功用及用法。
复制代码 代码如下:
import codecs
file=codecs.open(“lol.txt”,”w”,”utf-8″)
file.write(u”我”)
file.close()

读取ANSI编码的文件文件和utf-八编码的文书

读取ANSI编码文件

建立二个文本test.txt,文件格式用ANSI,内容为:
复制代码 代码如下:
abc中文

用python来读取
复制代码 代码如下:
# coding=gbk
print open(“Test.txt”).read()

结果:abc中文
读取utf-八编码文件(无BOM)
把文件格式改成UTF-八:
复制代码 代码如下:
结果:abc涓 枃

通晓,这里必要解码:
复制代码 代码如下:
# -*- coding: utf-8 -*-
import codecs
print open(“Test.txt”).read().decode(“utf-8”)

结果:abc中文

读取utf-8编码文件(有BOM)

某个软件在保留三个以UTF-八编码的文本时,暗中同意会在文件初始的地点插入多个不可知的字符(0xEF
0xBB
0xBF,即BOM)。在稍微软件能够操纵是或不是插入BOM。要是在有BOM的气象下,在读取时索要团结去掉这么些字符,python中的codecs
module定义了这一个常量:
复制代码 代码如下:
# -*- coding: utf-8 -*-
import codecs
data = open(“Test.txt”).read()
if data[:3] == codecs.BOM_UTF8:
    data = data[3:]
print data.decode(“utf-8”)

结果:abc中文
在看下边包车型大巴事例:
复制代码 代码如下:
# -*- coding: utf-8 -*-
data = open(“name_utf8.txt”).read()
u=data.decode(“utf-8”)
print u[1:]

张开utf-捌格式的文书并读取utf-8字符串后,解码形成unicode对象。可是会把附加的多个字符同样进行转变,形成三个unicode字符。该字符无法被打印。所感觉了健康突显,选择u[1:]的点子,过滤到第三个字符。
瞩目:在管理unicode粤语字符串的时候,必须首先对它调用encode函数,转变来其余编码输出。

设置python暗中同意编码

复制代码 代码如下:
import sys
reload(sys)
sys.setdefaultencoding(“utf-8”)
print sys.getdefaultencoding()

明日境遇了 python 编码难题, 报错音信如下
复制代码 代码如下:
Traceback (most recent call last):
  File “ntpath.pyc”, line 108, in join
UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xa1 in position 36:
ordinal not in range(128)

明确是日前的编码为ascii, 不能够深入分析0xa一(10进制为1陆一, 超越上限128).
进入python console后, 发掘默许编码确实是 ascii, 验证进程为:
在python二.陆中不恐怕调用sys.setdefaultencoding()函数来修改默许编码,因为python在开发银行的时候会调用site.py文件,在这一个文件中装置完默许编码后会删除sys的setdefaultencoding方法。不能够再被调用了. 
在规定sys已经导入的意况下, 能够reload sys那个模块然后, 再
sys.setdefaultencoding(‘utf八’)

复制代码 代码如下:
import sys
reload(sys)
sys.setdefaultencoding(“utf-8”)
print sys.getdefaultencoding()

实在有效, 依据 limodou 疏解,  site.py 是 python 解释器运转后,
暗中认可加载的四个脚本. 假使选取 python -S 运营以来, 将不会活动加载 site.py.

上边写的挺啰嗦的.

==================================

一.二 底部编码评释

在python源代码文件中只要有用到非ascii字符,比方粤语,那么须要在源码文件底部表明源代码字符编码,格式如下:

#-*- coding: utf-8 -*-

本条格式看起相比复杂,其实python只检查#、coding,编码等字符串,能够简写成#coding:utf-八,以至还足以写成#coding:u8。

 

Python常见编码至极(大致都冒出在Python二.x中)

Python中广泛的编码特别包含:SyntaxError: Non-ASCII character
、UnicodeDecodeError和UnicodeEncodeError等。

1.SyntaxError: Non-ASCII character

这种分外不是很常见,但最佳化解了。只假诺因为Python源码文件中设有不属于ascii字符,而且还要未有表明源码的编码格式,比方

#在Python2.x中,在文件头部没有指定编码格式

s = '土耳其大骗子'
print  s

#SyntaxError: Non-ASCII character '\xe5' in file /xxx/xxx/exercise-unicode.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

消除办法:在文件尾部注明编码格式 #!-*- encoding:utf-8
-*-或#!encoding:utf-8

Python二.x中1旦不在源码文件首行钦赐编码格式,则不能够在Python源码文件中冒出非ascii字符。那是出于Python解释器暗中同意将源码认为是ascii编码格式

2.UnicodeDecodeError

以此可怜则会并发在调用decode方法时,原因是Python将此外编码格式的字符转化为unicode编码,但是字符自个儿的编码格式和decode传入的编码格式不一样等,比如:

#Python2.x中

#!encoding:utf-8

s = '土耳其大骗子'
us = s.decode('gbk')

#异常
#UnicodeDecodeError: 'gbk' codec can't decode bytes in position 4-5: illegal multibyte sequence

下面这段代码字符串字符串s暗中同意的编码格式是“utf-八”(#!encoding:utf-8宣称的意趣就是:当前.py文件中有所的字符都是utf-八编码的),不过在选取decode转化为unicode编码是流传的编码格式为“gbk”,因而在倒车的时候抛出UnicodeDecodeError非常。还有一种情景是在encode的时候:

#Python2.x中
#! -*- encoding:utf-8 -*-

s = '土耳其大骗子'
us = s.encode('gbk')

#输出
#UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

此间是s是“utf-八”编码,直接使用s.encode(‘gbk’),实际上是利用了系统暗中认可的defaultencoding来解码,等价于

s.decode(defaultencoding).encode('gbk')

而s的实际上编码和defaultencoding(python2.x暗中认可是ascii)差别。

3.UnicodeEncodeError

不当的decode和encode方法会出现极度,举个例子选择decode方法将unicode字符串转化的时候

#! -*- encoding:utf-8 -*-

s = u'土耳其大骗子'
us = s.decode('utf-8')

#输出
#UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

鉴于在Python贰.x中,字符串转化为unicode编码的时候,能够透过unicode(‘xxx’)、u’xxx’、’xxx’.decode(‘utf-八’),可是本示例是将unicode编码的字符串解码,于是抛出“UnicodeEncodeError”非常

 

二.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") #解码错误

留神实例中注释掉的二行代码,对于unicode最佳不要一贯调用decode,str最好不要直接调用encode方法。因为1旦是直接调用,则一定于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...错误。

地点例子中注释掉的两行代码尽管施行就能报错,当然,若是笔者str可能unicode都在ascii编码范围,就从不难点。譬如s = "abc"; s.encode("utf-8")就不会不符合规律,语句试行后会再次来到2个跟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")

发表评论

电子邮件地址不会被公开。 必填项已用*标注