文件编码,要在第一行加入   

作者: 编程  发布:2019-09-05

那么先将文件中的内容由gb2312转换成Unicode,然后再把这些Unicode转换为UTF-8格式的字节串。完成这一步骤后,解析器把这些UTF-8字节串分段,解析。如果遇到使用Unicode字符串,那么就使用相应的UTF-8字节串创建Unicode字符串,如果程序中使用的是一般的字符串。

x = u"中文你好"
print s

test1.py

7.2 编码格式

在使用GB2312的程序中,通常采用EUC储存方法,以便兼容于ASCII。浏览器编码表上的“GB2312”,通常都是指“EUC-CN”表示法。

每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”(也称“区字节)”,第二个字节称为“低位字节”(也称“位字节”)。
“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上 0xA0)。 由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0-0xF7,“低位字节”的范围是0xA1-0xFE,占用的码位是 72*94=6768。其中有5个空位是D7FA-D7FE。

例如“啊”字在大多数程序中,会以两个字节,0xB0(第一个字节) 0xA1(第二个字节)储存。区位码=区字节 位字节(与区位码对比:0xB0=0xA0 16,0xA1=0xA0 1)。

GB 2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时,GB 2312收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

回顾一下使用Python解析器的流程:首先,先用编辑器编写好源代码,保存成文件。如果源代码中有编码声明而且用的编辑器支持该语法,那么该文件就以相应的编码方式保存在磁盘中。注意:编码声明和源文件的编码不一定是一致的,完全可以在编码声明中声明编码为UTF-8,但是用GB2312来保存源文件。

     我们可以看到,通过引入编码声明,我们可以正常地在使用中文了,而且在code 1和2中,控制台也能正确的把中文打印出来。但是,很明显,上面的代码也反映出了不少的问题:
    1、code 1 和 2在使用print时采用了不同的方式,1是直接print,而2在print之前先进行编码
    2、code 1和2中在同样的字符串查找同一个字符“我”,得出的结果不一样(分别是5和3)
    3、code 3 中直接打印unicode字符串 y时出现错误(这也是为什么code 2中要先进行编码的原因)

 

python自然语言编码转换模块codecs介绍

python对多国语言的处理是支持的很好的,它可以处理现在任意编码的字符,这里深入的研究一下python对多种不同语言的处理。

有一点需要清楚的是,当python要做编码转换的时候,会借助于内部的编码,转换过程是这样的:

复制代码代码如下:

原有编码 -> 内部编码 -> 目的编码

python的内部是使用unicode来处理的,但是unicode的使用需要考虑的是它的编码格式有两种,一是UCS-2,它一共有65536个码位,另一种是UCS-4,它有2147483648g个码位。对于这两种格式,python都是支持的,这个是在编译时通过--enable-unicode=ucs2或--enable-unicode=ucs4来指定的。那么我们自己默认安装的python有的什么编码怎么来确定呢?有一个办法,就是通过sys.maxunicode的值来判断: 

复制代码代码如下:

import sys
print sys.maxunicode

 

如果输出的值为65535,那么就是UCS-2,如果输出是1114111就是UCS-4编码。
我们要认识到一点:当一个字符串转换为内部编码后,它就不是str类型了!它是unicode类型:

复制代码代码如下:

a = "风卷残云"
print type(a)
b = a.unicode(a, "gb2312")
print type(b)

输出:

复制代码代码如下:

<type 'str'>
<type 'unicode'>

这个时候b可以方便的任意转换为其他编码,比如转换为utf-8:

复制代码代码如下:

c = b.encode("utf-8")
print c

c输出的东西看起来是乱码,那就对了,因为是utf-8的字符串。

 

好了,该说说codecs模块了,它和我上面说的概念是密切相关的。codecs专门用作编码转换,当然,其实通过它的接口是可以扩展到其他关于代码方面的转换的,这个东西这里不涉及。

复制代码代码如下:

#-*- encoding: gb2312 -*-
import codecs, sys

 

print '-'*60
# 创建gb2312编码器
look  = codecs.lookup("gb2312")
# 创建utf-8编码器
look2 = codecs.lookup("utf-8")

a = "我爱北京天安门"

print len(a), a
# 把a编码为内部的unicode, 但为什么方法名为decode呢,我的理解是把gb2312的字符串解码为unicode
b = look.decode(a)
# 返回的b[0]是数据,b[1]是长度,这个时候的类型是unicode了
print b[1], b[0], type(b[0])
# 把内部编码的unicode转换为gb2312编码的字符串,encode方法会返回一个字符串类型
b2 = look.encode(b[0])
# 发现不一样的地方了吧?转换回来之后,字符串长度由14变为了7! 现在的返回的长度才是真正的字数,原来的是字节数
print b2[1], b2[0], type(b2[0])
# 虽然上面返回了字数,但并不意味着用len求b2[0]的长度就是7了,仍然还是14,仅仅是codecs.encode会统计字数
print len(b2[0])

 

上面的代码就是codecs的使用,是最常见的用法。另外还有一个问题就是,如果我们处理的文件里的字符编码是其他类型的呢?这个读取进行做处理也需要特殊的处理的。codecs也提供了方法.

复制代码代码如下:

#-*- encoding: gb2312 -*-
import codecs, sys

 

# 用codecs提供的open方法来指定打开的文件的语言编码,它会在读取的时候自动转换为内部unicode
bfile = codecs.open("dddd.txt", 'r', "big5")
#bfile = open("dddd.txt", 'r')

ss = bfile.read()
bfile.close()
# 输出,这个时候看到的就是转换后的结果。如果使用语言内建的open函数来打开文件,这里看到的必定是乱码
print ss, type(ss)

上面这个处理big5的,可以去找段big5编码的文件试试。

 

 

 

注意: 编码声明和源文件的编码不一定是一致的,你完全可以在编码声明中声明编码为UTF-8,但是用GB2312来保存源文件。当然,我们不可能自寻烦恼,故意写错,而且好的IDE也能强制保证两者的一致性,但是,如果我们用记事本或者EditPlus等编辑器来编写代码的话,一不小心就会出现这种问题的。

原因是它不能识别中文编码。要在第一行加入   

文件编码,它代表源码文件内的所有内容都是根据词方式编码成二进制码流,存入到磁盘中的。

8.3 说明

GB2312是中国规定的汉字编码,也可以说是简体中文的字符集编码;GBK 是 GB2312的扩展 ,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名。

对于前者,方法是以字节的方式进行的,而且在GB2312中,每个汉字占用两个字节,因此得到的结果是5;对于后者,也就是 Unicode字符串,所有字符都是统一看待的,因此得到。

Python中有两种字符串,分别是一般的字符串(每个字符用8 bits表示)和Unicode字符串(每个字符用一个或者多个字节表示),它们可以相互转换。

所以在用python读写文件的时候,要注意文件编码是哪种,自己python解释器用哪种编码方式。

一、先说说编解码问题

编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。

图片 1

Eg:

1
2
str1.decode('gb2312')    #将gb2312编码的字符串转换成unicode编码
str2.encode('gb2312')    #将unicode编码的字符串转换成gb2312编码

python2.7 idle GUI界面打印中文会出现乱码,这是idle本身问题:

图片 2   

cmd界面的python2.7则是正常的:

图片 3

注意事项:

  •  s='中文' 如果是在utf8的文件中,该字符串就是utf8编码,如果是在gb2312的文件中,则其编码为gb2312。这种情况下,要进行编码转换,都需要先用decode方法将其转换成unicode编码,再使用encode方法将其转换成其他编码。
  • 在没有指定特定的编码方式时,都是使用的系统默认编码创建的代码文件。
  • 如果字符串是这样定义: s=u'中文' 则该字符串的编码就被指定为unicode了,即python的内部编码,而与代码文件本身的编码无关。只需要直接使用encode方法将其转换成指定编码即可
  • 如果一个字符串已经是unicode了,再进行解码则将出错,因此通常要对其编码方式是否为unicode进行判断isinstance(s, unicode) #用来判断是否为unicode 

得到一个.py文件后,我们就可以运行它了,这是,我们就把代码交给Python解析器来完成解析工作。解析器读入文件时,先解析文件中的编码声明,我们假设文件的编码为gb2312,那么先将文件中的内容由gb2312转换成Unicode,然后再把这些Unicode转换为UTF-8格式的字节串。

python 的eclips教程环境后写了一个测试程序。结果出现这样的错误:

s = '文斌'
print s.decode()

7.GB2312

否则Python使用默认的编码方式进行编码,也就是ASCII例子中的code 3)。当然ASCII是不可能正确编码中文的,因此Python报错。至此,上面的三个问题我们已经可以解析第一和第三个了。至于第二个问题,因为Python中有两种字符串,一般字符串和Unicode字符串,两者都有各自的字符处理方法。

    为什么?为什么?我们可以先在脑海中模拟一下我们使用Python的流程:首先,我们先用编辑器编写好源代码,保存成文件。如果源代码中有编码声明而且用的编辑器支持该语法,那么该文件就以相应的编码方式保存在磁盘中。注意:编码声明和源文件的编码不一定是一致的,你完全可以在编码声明中声明编码为UTF-8,但是用GB2312来保存源文件。当然,我们不可能自寻烦恼,故意写错,而且好的IDE也能强制保证两者的一致性,但是,如果我们用记事本或者EditPlus等编辑器来编写代码的话,一不小心就会出现这种问题的。
    得到一个.py文件后,我们就可以运行它了,这是,我们就把代码交给Python解析器来完成解析工作。解析器读入文件时,先解析文件中的编码声明,我们假设文件的编码为gb2312,那么先将文件中的内容由gb2312转换成Unicode,然后再把这些Unicode转换为UTF-8格式的字节串。完成这一步骤后,解析器把这些UTF-8字节串分段,解析。如果遇到使用Unicode字符串,那么就使用相应的UTF-8字节串创建Unicode字符串,如果程序中使用的是一般的字符串,那么解析器先将UTF-8字节串通过Unicode转换成相应编码(这里就是gb2312编码)的字节串,并用其创建一般的字符串对象。也就是说,Unicode字符串跟一般字符串在内存中的存放格式是不一样的,前者使用UTF-8的格式,后者使用GB2312格式。
    好了,内存中的字符串存放格式我们知道了,下面我们要了解print的工作方式。print其实只是负责把内存中相应的字节串交给操作系统,让操作系统相应的程序(譬如cmd窗口)进行显示。这里有两种情况:
   1、若字符串是一般的字符串,那么print只需把内存中相应的字节串推送给操作系统。如例子中的code 1。
    2、如果字符串是Unicode字符串,那么print在推送之前先进行相应的encode:我们可以显示使用Unicode的encode方法使用合适的编码方式来编码(例子中code 2),否则Python使用默认的编码方式进行编码,也就是ASCII(例子中的code 3)。当然ASCII是不可能正确编码中文的,因此Python报错。
    至此,上面的三个问题我们已经可以解析第一和第三个了。至于第二个问题,因为Python中有两种字符串,一般字符串和Unicode字符串,两者都有各自的字符处理方法。对于前者,方法是以字节的方式进行的,而且在GB2312中,每个汉字占用两个字节,因此得到的结果是5;对于后者,也就是Unicode字符串,所有字符都是统一看待的,因此得到3。
     虽然上面只提到了控制台程序的中文问题,但是文件读写以及网络传输中出现的中文问题在原理上都是类似的。Unicode的出现可以很大程度上解决软件的国际化问题,同时Python为Unicode提供了极为良好的支持,因此,我建议大家在编写Python的程序时,都统一使用Unicode方式。保存文件时使用UTF-8的编码方式。How to Use UTF-8 with Python有详细的描述,

头文件后就指定了python解析器的编码方式,就不会报错了。

下面是一下大神的总结

编码:

计算机中存放的都是0和1的二进制值。8个位对应一个字节,常用16进制来表示,注意是表示,因为是2^4,所以0xF就表示这个字节,0x是16进制的意思,0xF就表示了这个字节里是11111111

ASCII的编码规则,由于最初只是为英文字母所考虑的,而英文只有26个字母,以及加上其他大小写字母,常见的字符,常见数字等,所有的加起来,也就几十个,而一个字节8位中前7位的理论上可以表示27=128个字符,所以对于设计出来的编码规则来说,只需要用一个字节来表示,就足够了。

Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

UTF-8是Unicode的实现方式之一。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

Unicode符号范围(十六进制)  UTF-8编码方式(二进制)
0000 0000-0000 007F       0xxxxxxx
0000 0080-0000 07FF       110xxxxx 10xxxxxx
0000 0800-0000 FFFF       1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

python 头文件:

1
# -*- coding: utf-8 -*-
对此格式的详细解释是:
    1    如果没有此文件编码类型的声明,则python默认以ASCII编码去处理,如果你没声明编码,但是文件中又包含非ASCII编码的字符的话,python解析器去解析的python文件,自然就会报错了。
    2    必须放在python文件的第一行或第二行
    3    更加精确的解释是: "coding[:=]s*([-w.] )"
   
    4    为了照顾特殊的Windows中的带BOM(’xefxbbxbf’)的UTF-8:
             如果你的python文件本身编码是带BOM的UTF-8,即文件前三个字节是:’xefxbbxbf’,那么:
             i    即使你没有声明文件编码,也自动当做是UTF-8的编码
             ii    如果你声明了文件编码,则必须是声明了(和你文件编码本身相一致的)UTF-8
             否则(由于声明的编码和实际编码不一致,自然)会报错

python编码

Python内部的字符串一般都是 Unicode编码。代码中字符串的默认编码与代码文件本身的编码是一致的。所以要做一些编码转换通常是要以Unicode作为中间编码进行转换的,即先将其他编码的字符串解码(decode)成 Unicode,再从 Unicode编码(encode)成另一种编码。
        decode 的作用是将其他编码的字符串转换成 Unicode 编码,eg name.decode(“GB2312”),表示将GB2312编码的字符串name转换成Unicode编码
        encode 的作用是将Unicode编码转换成其他编码的字符串,eg name.encode(”GB2312“),表示将GB2312编码的字符串name转换成GB2312编码

所以在进行编码转换的时候必须先知道 name 是那种编码,然后 decode 成 Unicode 编码,最后载 encode 成需要编码的编码。当然了,如果 name 已经就是 Unicode 编码了,那么就不需要进行 decode 进行解码转换了,直接用 encode 就可以编码成你所需要的编码。

例子:读取一个文件编码格式为gbk的文件,然后输出一个utf8格式的文件

        # coding: UTF-8
        
        fp1 = open('test.txt', 'r')
        info1 = fp1.read()
        # 已知是 GBK 编码,解码成 Unicode
        tmp = info1.decode('GBK')
        
        fp2 = open('test.txt', 'w')
        # 编码成 UTF-8 编码的 str
        info2 = tmp.encode('UTF-8')
        fp2.write(info2)
        fp2.close()         

设置python编码方法:注意要先reload
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
print sys.getdefaultencoding()

unicode是一个内置函数,第二个参数指示源字符串的编码格式。
s1 = u'中文'
s2 = unicode('中文','gbk')
s3 = s1.decode('gbk')

在vim中查看文件编码格式
:set fileencoding

2.扩展的ASCII编码

一个字节中的后7位总共只能表示128个不同的字符,英语用这些字符已经足够了,可是要表示其他语言却是不够。比如,在法语中,字母上方有注音的符号,就无法用ASCII表示。于是,一些国家就利用了字节中闲置的最高位编入新的符号。这样一来,就可以表示最多256个符号,这就是扩展ASCII 码,所以现在有7位和8位的两种ASCII码,扩展的ASCII 码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号。但是,不管怎样,0~127表示的字符是一样的,不同的只是128~255.

当然,这是自寻烦恼,而且好的IDE也应该保证两者的一致性。但是,如果。用记事本或者EditPlus等编辑器来编写代码的话,可能就会出现这种问题的。得到一个.py文件后,可以运行它。这是把代码交给Python解析器来完成解析工作。解析器读入文件时,先解析文件中的编码声明,假设文件的编码为gb2312。

# -*- coding: GBK -*-

 

python之decode、encode及codecs模块

保存文件时使用UTF-8的编码方式。How to Use UTF-8 with Python有详细的描述,大家可以参考一下。Python中能导致出现中文问题的地方还很多,譬如文件的读写,网络数据的传输等,希望大家能多多交流,共同解决这些问题。

SyntaxError: Non-ASCII character 'xd6' in file G:workspacechinese_problemsrctest.py on line 1, but no encoding declared; see for details
   说是遇到非ASCII字符了,并让我们参考pep-0263。PEP-0263(Python Enhancement Proposal)上面说得很清楚了,Python也意识到了国际化问题,并提出了解决方案。根据提案上面的要求,我们有如下代码
 # -*- coding:gb2312 -*- #必须在第一行或者第二行
print "-------------code 1----------------"
a = "中文a我爱你"
print a
print a.find("我")
b = a.replace("爱", "喜欢")
print b
print "--------------code 2----------------"
x = "中文a我爱你"
y = unicode(x, "gb2312")
print y.encode("gb2312")
print y.find(u"我")
z = y.replace(u"爱",u"喜欢")
print z.encode("gb2312")
print "---------------code 3----------------"
print y    程序运行的结果如下:
-------------code 1----------------
中文a我爱你
5
中文a我喜欢你
--------------code 2----------------
中文a我爱你
3
中文a我喜欢你
---------------code 3----------------
Traceback (most recent call last):
  File "G:Downloadseclipseworkspacepsrchello.py", line 16, in <module>
    print y
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

Python内部的字符串一般都是 Unicode编码。代码中字符串的默认编码与代码文件本身的编码是一致的。所以要做一些编码转换通常是要以Unicode作为中间编码进行转换的,即先将其他编码的字符串解码(decode)成 Unicode,再从 Unicode编码(encode)成另一种编码。
        decode 的作用是将其他编码的字符串转换成 Unicode 编码,eg name.decode(“GB2312”),表示将GB2312编码的字符串name转换成Unicode编码
        encode 的作用是将Unicode编码转换成其他编码的字符串,eg name.encode(”GB2312“),表示将GB2312编码的字符串name转换成GB2312编码

四、Python模块之codecs 

python对多国语言的处理是支持的很好的,它可以处理现在任意编码的字符,这里深入的研究一下python对多种不同语言的处理。
有一点需要清楚的是,当python要做编码转换的时候,会借助于内部的编码,转换过程请参考上文第一张图片。

Unicode编码有两种,一种是UCS-2,用两个字节编码,共65536个码位;另一种是UCS-4,用4个字节编码,共2147483648个码位。

python都是支持的,这个是在编译时通过--enable- unicode=ucs2或--enable-unicode=ucs4来指定的。那么我们自己默认安装的python有的什么编码怎么来确定呢?有一个 办法,就是通过sys.maxunicode的值来判断:

1
2
import  sys
print  sys.maxunicode

如果输出的值为65535,那么就是UCS-2,如果输出是1114111就是UCS-4编码。  

我们要认识到一点:当一个字符串转换为内部编码后,它就不是str类型了!它是unicode类型

1
2
3
4
a  =   " 风卷残云 "
print  type(a)
b  =  unicode(a,‘gb2312')
print  type(b)

运行结果:

1
2
<type 'str'>
<type 'unicode'>

这个时候b可以方便的任意转换为其他编码,比如转换为utf-8

1
2
c  =  b.encode(’utf8')
print  c

好了,该说说codecs模块了,它和我上面说的概念是密切相关的。codecs专门用作编码转换,当然,其实通过它的接口是可以扩展到其他关于代码方面的转换的,这个东西这里不涉及。

  

  

  

参考文档: 

 

 

首先先让大家看一下Python解析器的全流程:我们先用编辑器编写好源代码,保存成文件。如果源代码中有编码声明而且用的编辑器支持该语法,那么该文件就以相应的编码方式保存在磁盘中。

,我们先要了解Python中有两种字符串,分别是一般的字符串(每个字符用8 bits表示)和Unicode字符串(每个字符用一个或者多个字节表示),它们可以相互转换。关于Unicode,Joel Spolsky 在 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)中有生动的说明,Jason Orendorff在 Unicode for programmers 有着更为全面的描述,在此我就不再多说什么了。来看下面的代码:

没有指定python编码方式,默认肯定为ascii,所以就没办法编码文字  '文斌'  了,所以运行这个脚本肯定报错,当你用  # -*- coding: utf-8 -*- 

使用codecs模块,在Python中完成字符编码

 

字符的编码是按照某种规则在单字节字符和多字节字符之间进行转换的某种方法。从单字节到多字节叫做decoding,从多字节到单字节叫做encoding。在这些规则中经常用到的无非是UTF-8和GB2312两种。

 

在Python中,codecs模块提供了实现这些规则的方法,通过模块公开的方法我们能够方便地获取某种编码方式的Encoder和 Decoder工厂函数(Factory function),以及StreamReader、StreamWriter和StreamReaderWriter类。

 

使用“import codecs”导入codecs模块。

 

codecs模块中重要的函数之一是lookup,它只有一个参数encoding,指的是编码方式的名称,即utf-8或者gb2312等等。如下示例:

>>> import codecs>>> t = codecs.lookup("utf-8")>>> print t(<built-in function utf_8_encode>, <function decode at 0x00AA25B0>, <class encodings.utf_8.StreamReader at 0x00AA0720>, <class encodings.utf_8.StreamWriter at 0x00AA06F0>)>>> encoder = t[0]>>> decoder = t[1]>>> StreamReader = t[2]>>> StreamWriter = t[3]

lookup函数返回一个包含四个元素的TUPLE,其中t[0]是encoder的函数引用,t[1]是decoder的函数引用,t[2] 是UTF-8编码方式的StreamReader类对象引用,t[3]是UTF-8编码方式的StreamWriter类对象引用相信对Python熟悉的你肯定知道接下来该怎么用它们了。

 

codecs模块还提供了方便程序员使用的单独函数,以简化对lookup的调用。它们是:

``

  • getencoder(encoding)
  • getdecoder(encoding)
  • getreader(encoding)
  • getwriter(encoding)

如果我们只是想获取一种utf-8编码的encoder方法,那么只需要这样做:

>>> encoder = codecs.getencoder("utf-8")

 

另外,对于StreamReader和StreamWriter的简化, codecs模块提供一个open方法。相对于built-in对象File的open方法,前者多了三个参数encoding, errors, buffering。这三个参数都是可选参数,但是对于应用来说,需要明确指定encoding的值,而errors和buffering使用默认值即可。使用方法如下:

>>> fin = codecs.open("e:\mycomputer.txt", "r", "utf-8")>>> print fin.readline()这是我的电脑>>> fin.close()

 

总结一下,codecs模块为我们解决的字符编码的处理提供了lookup方法,它接受一个字符编码名称的参数,并返回指定字符编码对应的 encoder、decoder、StreamReader和StreamWriter的函数对象和类对象的引用。为了简化对lookup方法的调用, codecs还提供了getencoder(encoding)、getdecoder(encoding)、getreader(encoding)和 getwriter(encoding)方法;进一步,简化对特定字符编码的StreamReader、StreamWriter和 StreamReaderWriter的访问,codecs更直接地提供了open方法,通过encoding参数传递字符编码名称,即可获得对 encoder和decoder的双向服务。

 

 

 

 

  1. 有关Python系统文件进行介绍指导
  2. 如何正确的使用Python函数
  3. 对Python 构建工具进行详细介绍分析
  4. PythonAndroid浅析Python优势所在
  5. 如何使用Python模块解析配置文件?

Python的中文问题解决办法

unicode是python中的字符集,utf-8是unicode的一种实现,所以python2中有string和unicode两种字符串,string就是按照python编码的,unicode是字符集,有人称unicode为内码。

5.UTF8编码

事实证明,对可以用ASCII表示的字符使用UNICODE并不高效,因为UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对 他毫无用处。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即UTF(Universal Transformation Format)。目前存在的UTF格式有:UTF-7, UTF-7.5, UTF-8, UTF-16, 以及 UTF-32。

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码(定长码),也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第 一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传 送文字的应用中,优先采用的编码。

UTF-8用1~4个字节对Unicode进行编码。从Unicode到UTF-8的编码方式如下:

000000 - 00007F║0xxxxxxx
000080 - 0007FF║110xxxxx 10xxxxxx
000800 - 00FFFF║1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF║11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同; 
带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要二个字节编码(Unicode范围由); 
其他基本多文种平面(BMP)中的字符(这包含了大部分常用字)使用三个字节编码; 
其他极少使用的Unicode 辅助平面的字符使用四字节编码; 
UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。

UTF-8解析算法:

如果字节(Byte)的第一位为0,则B为ASCII码,并且Byte独立的表示一个字符; 
如果字节(Byte)的第一位为1,第二位为0,则Byte为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码; 
如果字节(Byte)的前两位为1,第三位为0,则Byte为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示; 
如果字节(Byte)的前三位为1,第四位为0,则Byte为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示; 
如果字节(Byte)的前四位为1,第五位为0,则Byte为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示。

如果程序中使用的是一般的字符串,那么解析器先将UTF-8字节串通过Unicode转换成相应编码这里就是gb2312编码)的字节串注:普通的,非unicode的,即ascii ),并用其创建一般的字符串对象。也就是说,Unicode字符串跟一般字符串在内存中的存放格式是不一样的,前者使用UTF-8的格式,后者使用GB2312格式。

SyntaxError: Non-ASCII character 'xbd' in file E:workspacemakeUpdatafilesIndexsrcmakeIndex.py on line 12, but no encoding declared; see for details

9.Python idle默认编码方式

如下操作均在Python2.7 idle中实验

图片 4

图片 5

说明:1.'a'的编码仍然是'a',‘中'编码为0xd6和0xd0两个字节( 而且是0x80~0xFF 范围内),说明编码方式为扩展的ASCII(ANSI)

参考

后续继续更新

 

  

虽然上面只提到了控制台程序的中文问题,但是文件读写以及网络传输中出现的中文问题在原理上都是类似的。Unicode的出现可以很大程度上解决软件的国际化问题,同时Python为Unicode提供了极为良好的支持,因此,我建议大家在编写Python的程序时,都统一使用Unicode方式。

    运行上述代码,Python会给出下面的错误提示

再比如最常看到的:

 

...

python编码,是指python内设置的解码方式。如果不设定的话,python2默认是ascii解码。在源码文件开头(一定是第一行):#-*-coding:UTF-8-*-,源码文件的设置解码方式是UTF-8

1. notepad

对于我们经常使用的记事本,“文件”  ->  “另存为”,可查看到当前的编码方式:

图片 6

好了,内存中的字符串存放格式我们知道了,下面我们要了解print的工作方式。print其实只是负责把内存中相应的字节串交给操作系统,让操作系统相应的程序譬如cmd窗口)进行显示。这里有两种情况:

系统编码,可以通过locale命令查看(LINUX)), centos7 配置文件在/etc/profile.d/lang.sh

Python字符串的encode与decode研究心得——解决乱码问题

 

为什么Python使用过程中会出现各式各样的乱码问题,明明是中文字符却显示成“/xe4/xb8/xad/xe6/x96/x87”的形式?为什么会报错“UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)”?本文就来研究一下这个问题。


字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 

decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。 

encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。 

因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码


代码中字符串的默认编码与代码文件本身的编码一致。 

如:s='中文'

如果是在utf8的文件中,该字符串就是utf8编码,如果是在gb2312的文件中,则其编码为gb2312。这种情况下,要进行编码转换,都需要先用decode方法将其转换成unicode编码,再使用encode方法将其转换成其他编码。通常,在没有指定特定的编码方式时,都是使用的系统默认编码创建的代码文件。 

如果字符串是这样定义:s=u'中文'

则该字符串的编码就被指定为unicode了,即python的内部编码,而与代码文件本身的编码无关。因此,对于这种情况做编码转换,只需要直接使用encode方法将其转换成指定编码即可。


如果一个字符串已经是unicode了,再进行解码则将出错,因此通常要对其编码方式是否为unicode进行判断:

isinstance(s, unicode)  #用来判断是否为unicode 

用非unicode编码形式的str来encode会报错 


 如何获得系统的默认编码? 

#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()  

该段程序在英文WindowsXP上输出为:ascii 


在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。 

如在UliPad中运行如下代码:

s=u"中文"
print s 

会提示:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)。这是因为UliPad在英文WindowsXP上的控制台信息输出窗口是按照ascii编码输出的(英文系统的默认编码是ascii),而上面代码中的字符串是Unicode编码的,所以输出时产生了错误。

将最后一句改为:print s.encode('gb2312')

则能正确输出“中文”两个字。

若最后一句改为:print s.encode('utf8')

则输出:/xe4/xb8/xad/xe6/x96/x87,这是控制台信息输出窗口按照ascii编码输出utf8编码的字符串的结果。


unicode(str,'gb2312')与str.decode('gb2312')是一样的,都是将gb2312编码的str转为unicode编码 

使用str.__class__可以查看str的编码形式


原理说了半天,最后来个包治百病的吧:)

 

[python] view plain copy

 

  1. #!/usr/bin/env python  
  2. #coding=utf-8  
  3. s="中文"  
  4.   
  5. if isinstance(s, unicode):  
  6. #s=u"中文"  
  7.     print s.encode('gb2312')  
  8. else:  
  9. #s="中文"  
  10.     print s.decode('utf-8').encode('gb2312')  

 

 

 

 

 

1、若字符串是一般的字符串,那么print只需把内存中相应的字节串推送给操作系统。如例子中的code 1。
2、如果字符串是Unicode字符串,那么print在推送之前先进行相应的encode:我们可以显示使用Unicode的encode方法使用合适的编码方式来编码例子中code 2)

在test.py保存的时候,会按照系统编码方式GBK的方式(有的编辑器也能自定义编码格式),编码成gbk二进制码流,存储到磁盘上。当运行该程序时。gbk二进制码流调入内存,并按照python设置的解码方式解码,也就是按照UTF-8的方式解码,所以结果不是错误提示,就是显示出来的是乱码。

3.ANSI编码

也是美国国家标准协会(American National Standard Institute , ANSI )制订的标准。为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。比如:汉字 '中' 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。

不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。

  • 在简体中文系统下,ANSI 编码代表 GB2312 编码
  • 在日文操作系统下,ANSI 编码代表 JIS 编码

不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。

ANSI编码表示英文字符时用一个字节,表示中文用两个字节,而unicode不管表示英文字符还是中文都是用两个字节来表示。

注:这里仅指源代码即脚本代码的纯代码转换) 完成这一步骤后,解析器把这些UTF-8字节串分段,解析。如果遇到使用Unicode字符串注:比如遇到 u'中国a我爱你') ,那么就使用相应的UTF-8字节串创建Unicode字符串。

 

3.UltraEdit

 不同编码的文本,是根据文本的前两个字节来定义其编码格式的,定义如下:

ANSI:        无格式定义; 
Unicode:       前两个字节为FFFE; 
Unicode big endian: 前两字节为FEFF;  
UTF-8:        前两字节为EFBB; 
这样通过前面两个字节就可以判定出文件的具体格式了。

那么解析器先将UTF-8字节串通过Unicode转换成相应编码这里就是gb2312编码)的字节串,并用其创建一般的字符串对象。也就是说,Unicode字符串跟一般字符串在内存中的存放格式是不一样的,前者使用UTF-8的格式,后者使用GB2312格式。

系统编码:locale:gbk
python源文件test.py
#coding='UTF-8'
s='文斌'
print s

8.1 名称及制定时间

GBK全称《汉字内码扩展规范》,全国信息技术标准化技术委员会1995年12月1日制订。

三、系统中常见的编码方式

4.Unicode编码

Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称,是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。

但即使扩展到256个符号也不够用,比如汉字据统计有10万个以上,而且同一个数值在各国的语言中表示的却不同,比如130在法语里面é,而在希腊语里面则代表Gimel,于是UNICODE应运而生。

Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U ”,例如字母“A”的编码为 004116 和字符“?”的编码为 20AC16。所以“A”的编码书写为“U 0041”。但Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

6.ANSI与ASCII编码区别

  • 字面上差异:ANSI指美国国家标准协会,ASCII指美国信息互换标准代码
  • ANSI可以说是ASCII的扩展(为了支持非拉丁语系的语言)一方面,他将ascii码扩展到8bits,增加了0x80-0xff共128个字符。另一方面,在cjk(chinese japanese korean)系统中,ANSI在不同语言中有不同的具体标准,在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。
  • ansi编码,就是一种未经国际标准化的编码(也没办法标准化,因为扩展部分的内码存在交集);而Unicode为国际化的编码。

2.notepad

点击“菜单栏”  ->  “格式”可以查看到:

图片 7

还可直接对其进行转换,转换完成后保存文件。

7.1 名称及制定时间

《信息交换用汉字编码字符集》是由中国国家标准总局1980年发布,标准号是GB 2312—1980,所以简称为GB2312。

8.GBK

7.3 特点

GB 2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。
对于人名、古汉语等方面出现的罕用字,GB 2312不能处理,这导致了后来GBK及GB 18030汉字字符集的出现。

二、查看文本编码的方式 

8.2 编码格式

GBK编码,是在GB2312-80标准基础上的内码扩展规范,使用了双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),共23940个码位,共收录了21003个汉字,完全兼容GB2312-80标准,支持国际标准ISO/IEC10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。GBK编码方案于1995年10月制定, 1995年12月正式发布,目前中文版的WIN95、WIN98、WINDOWS NT以及WINDOWS 2000、WINDOWS XP、WIN 7等都支持GBK编码方案。

GBK 是 GB2312的扩展 ,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名。

1.ASCII编码

上世纪70年代,美国国家标准协会(American National Standard Institute , ANSI )制订了ASCII码(American Standard Code for Information Interchange,美国标准信息交换码)

使用7 位二进制数共128个组合来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。

第0~32号及第127号(共34个)是控制字符或通讯专用字符,如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BEL(振铃)等

第33~126号(共94个)是字符,其中第48~57号为0~9十个阿拉伯数字;65~90号为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。

最高位(b7)用作奇偶校验位,所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种:

  • 奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1
  • 偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1

本文由9159.com发布于编程,转载请注明出处:文件编码,要在第一行加入   

关键词: 9159.com