美文网首页python基础
02、python编码问题详解

02、python编码问题详解

作者: vannesspeng | 来源:发表于2018-10-24 17:09 被阅读15次

    在讨论python编码之前,我先了解了几种编码的由来。

    一、编码类型

    1、ascci码

    ascci码由美国人发明,用1个字节(byte)存储英文和字符,前期用了128个,后来新加了其他欧洲国家的符号,128~255这一段。

    256个字符,基本上就是键盘上的所有字符。

    2、unicode

    2个byte,65535。因为后来发现还有其他国家的语言,而256个字符太少。

    3、utf-8

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

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

    UTF-8的编码规则很简单,只有二条:

    对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

    对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

    下表总结了编码规则,字母x表示可用编码的位。

    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

    4、GBK

    GBK全称《汉字内码扩展规范》(GBK即“国标)就是国家制定的标准。

    其实GBK在就是将每个汉字对应一个数字编码,http://www.mytju.com/classCode/tools/encode_gb2312.asp 这个网址可以查看到具体的编码对应关系:

    比如:中国  二字,对应的各种编码如下。

    二、为什么要转码?

    在python程序运行过程中,如果遇到编码不一致(就好像中国人和美国人在一起,如果语言不通的话,就无法沟通。),就需要进行转码。相当于需要有一个翻译。

    在运行Python程序的过程中,会涉及到三个方面的编码:

    1)Python程序文件本身的编码(test.py文件的编码)--自身文件

    2)Python程序运行时环境的编码(比如securecrt,类似mysql客户端连接时的编码)--客户端

    3)Python程序读取外部文件的编码(引用外部文件的编码)--外部文件

    下面对于以上三种情况为什么需要转码分别进行说明:

    情况一:(自身文件编码问题)

    python2默认编码为ascii,如果我们写的代码里面有非ascii字符,比如中文字符,py程序就会不认识。

    就相当于两个人都用普通话在沟通,其中某一个人突然蹦出一句家乡话,另外一个人突然就懵逼了,同样,python也懵逼了。

    记得刚开始接触python时,就碰到了经典错误,然后网上各种找资料,后来照着网上前辈们的设置,也没有深究其原理。

    经典错误范例:

    #!/usr/bin/env python

    print '你好 杰克'

    运行时会报错:

    SyntaxError: Non-ASCII character '\xe4' in file t.py on line 4, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

    错误原因:python2默认的编码为ascii,python3默认编码为utf-8,而文件里面包含了非ASCII字符,所以他肯定不认识,就报错了。

    可以通过sys模块查看默认编码:

    >>> sys.getdefaultencoding()

    'ascii'

    怎么解决?

    针对情况一解决方法:(目的都是将默认编码修改成utf-8,这样,程序既可以认识ascii,又可以认识utf-8了)

    解决方法一:

        import sys

        reload(sys)

        sys.setdefaultencoding('utf-8')

    解决方法二:

        #coding:utf8

    解决方法三:

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

    情况二(客户端编码问题) 

    我们在使用mysql时,如果客户端设置为latin,而服务端为utf-8,查询内容有中文时,就会出现乱码。同样,我们在使用python时,secureCRT也是客户端,服务端就是我们连接的服务器。

    范例:

    1、客户端设置secureCRT编码为UTF-8

    2、服务端测试

    3、设置客户端为非utf-8时,就会出现乱码

    结果如下:

    而且从步骤2中也可以看出,python自动识别变量a='中国test'为utf-8的编码,如果客户端(secureCRT)和服务端(python)编码不一致时,就会出现乱码。

    情况二解决办法:设置客户端的编码格式和服务端一致!

    情况三:读取外部文件时,出现乱码

    比较典型的就是:当我们从windows上编辑一个文件,上传到linux上时,会惊奇的发现^M符号。这个就是因为windows和linux的回车换行符不一致导致的,此时如果是python文件时,python也会报错。

    我们在linux先查看时会有特殊符号:

    这时,如果我们需要去掉^M,需要使用dos2unix工具转换一下,去掉windows上的格式。

    三、编码怎么转换

    unicode为桥梁,utf-8和gbk互转需要经过unicode这个翻译,不然他们二者是无法直接沟通。

    操作范例:

    1、查看默认编码,python遇到中文字符,会识别他是utf-8编码,chardet模块可以识别编码格式,但是也不是100%,下面他识别出myname为utf-8的概率为75%。

    2、将utf-8转为unicode编码

    utf-8转为unicode编码是,需要指定他本身是什么格式的编码,类似于加密。查看myname_unicode变量时,发现他是unicode编码格式了。

    3、将unicode编码转为utf-8

    具体转换操作如下:

     例子:

        >>> a=u'中国' #unicode编码格式的字符串

        >>> a_utf8=a.encode('utf-8') #将unicode转成utf-8编码格式

        >>> a_utf8

        '\xe4\xb8\xad\xe5\x9b\xbd'

        >>> a_unicode=a_utf8.decode('utf-8') #从utf8编码格式转回unicode编码格式

        >>> a_unicode

        u'\u4e2d\u56fd'

        >>> a

        u'\u4e2d\u56fd'

        >>>

        >>> b_gbk=a_unicode.encode('gbk') #将上面unicode格式的转成gbk编码格式

        >>> b_gbk

        '\xd6\xd0\xb9\xfa'

        >>> b_unicode=b_gbk.decode('gbk') #转回unicode编码格式

        >>> b_unicode #最后发现,a_unicode、b_unicode和原始的unicode编码的a都相等。

        u'\u4e2d\u56fd'

        >>> a_unicode

        u'\u4e2d\u56fd'

        >>> a

        u'\u4e2d\u56fd'

        >>>

    a.encode(* *):将a 编码 为 * *编码格式的字符串或unicode对象

    a.decode(* *):将a 解码 为 unicode编码格式的字符串或unicode对象

     另外:

    Python将字符串格式的unicode编码转换成unicode编码,如:\u53eb\u6211,需要转换成中文时有两种方式

    1.使用eval:

    eval("u"+"\'"+unicodestr+"\'")

    2.使用decode:

    str1 = '\u4f60\u597d' 

    print str1.decode('unicode_escape') 

    你好

    unicodestr.decode('unicode_escape')  # 将转义字符\u读取出来

    相关文章

      网友评论

        本文标题:02、python编码问题详解

        本文链接:https://www.haomeiwen.com/subject/liyxtqtx.html