zoukankan      html  css  js  c++  java
  • python 2.7编码问题

    问题引入

    先看下面的代码,代码用utf8编码格式保存.

    print("中")
    

    仅有一行代码,但是这个代码无论在ubuntu下还是win7下都会报错,错误信息类似是下面的内容:

    SyntaxError: Non-ASCII character 'xe4' in file xxx, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
    

    错误的原因是python 2.7默认python代码中只有ASCII编码.而代码中有"中"这个汉字.python解释器处理到汉字时,发现ASCII码没办法表示,就报错了.修改如下:

    # coding:utf-8
    print("中")
    

    加上# coding:utf-8意思是告诉python解释器,源代码的编码是utf-8,python解释器就用utf-8的形式处理源代码,utf-8可以表示"中"这个汉字.再在命令行窗口中运行代码,虽然不报错,且Ubuntu下显示正常,但是在windows命令行窗口中显示显示的不是汉字"中".为什么?这个涉及到的问题比较多,分步骤讨论.

    str,unicode

    str是字节组成的序列.需要强调的是,str必须显示或隐式地指定字符编码的时候,str和字符才能对应起来.同一个str,字符编码不同时,显示的内容就不同.这个非常容易理解,对于2个字节组成的str,utf-8和gbk代表的字符肯定是不一样的.python字符串默认是str型.之前的print("中")实际上输出的是str类型的字符串.看下面的代码.

    # coding:utf-8
    a = "中"
    print(type(a))
    print(len(a))
    

    上面代码输出是str, 长度为3. str表示"中"是str类型,长度为3表示"中"由3个字节组成.内存中是以utf-8保存字符串的,"中"的utf-8编码是3个字节,所以len的输出为3.
    再看下面代码

    # coding:utf-8
    a = u"中"
    print(type(a))
    print(len(a))
    

    "中"之前加一个前缀u,声明这里的"中"是unicode类型.unicode类型的字符串有几个字符,长度就是几,可以直观地看出来,不用再纠结字符在内存中是几个字节.这样就大大减轻了程序员的思维负担.

    print函数自动转码问题

    写程序时经常会用print函数测试输出,这就涉及到输出内容的编码.看下面代码

    # coding:utf-8
    import sys
    print (sys.stdout.encoding)
    

    这个代码在windows下输出是cp936,Ubuntu下输出是utf-8. 参数是str类型或者unicode类型,print函数会做不同处理,分开讨论.

    str

    输入参数是str类型时,print函数会把str转成sys.stdout.encoding指定的编码输出.对于汉字"中",python解释器把汉字"中"转化成utf-8(源代码的coding:utf-8指定)编码,占3个字节,类型为str.调用print函数时,python解释器把这3个字节当成sys.stdout.encoding指定的编码输出.Ubuntu系统中sys.stdout.encoding为utf-8,,肯定正常,因为本身是按utf-8形式转成3个字节的,再以utf-8显示,没问题.Windows系统中,sys.stdout.encoding是cp936,本身那3个字节是表示一个utf-8编码,现在以cp936的形式输出,就得到一个奇怪结果.这就解释了第1部分中的问题.如果字节中有超出cp936编码的内容,会直接报错.

    unicode

    unicode就比较简单了,不存在转码的问题.输入的unicode编码是什么,就输出对应的字符.

    解决问题

    要想让在windows系统下正常显示"中",转下码就可以了.代码如下.

    import sys
    a = "中"
    print a.decode("utf-8").encode(sys.stdout.encoding)
    

    先转成unicode,再转成sys.stdout.encoding编码.可以unicode当成"中转站",任何编码都能转成unicode,unicode也能转成任何编码.这个思路在处理不同操作系统的路径问题时非常有用.

    注意

    1. python 2中程序运行过程中应该使用unicode,最后返回结果时再根据需要转成utf-8或gbk.不要使用setdefaultencoding('utf-8'),原因见参考资料.
    2. 凡是和输出有关的最好都转化成sys.getfilesystemencoding()编码再输出.

    参考资料

    1. Why does Python print unicode characters when the default encoding is ASCII?
    2. unicode编码列表
    3. GBK 编码
    4. 立即停止使用 setdefaultencoding('utf-8')以及为什么
  • 相关阅读:
    error: readline/readline.h: No such file or directory
    ImportError: No module named setuptools
    ImportError: No module named argparse
    为python安装pip
    yum源安装配置
    n元一维向量向左循环移位i的几种算法
    以空间换时间编程策略的细节问题以及解决方案
    Hash(散列函数)简单应用引出解决散列冲突的四种方法
    随机取样
    排序问题
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/7285004.html
Copyright © 2011-2022 走看看