zoukankan      html  css  js  c++  java
  • 也来谈谈python编码

    一、coding:utf-8

    让我们先来看一个示例,源码文件是utf-8格式:

    print('你好 python')
    

    当使用python2执行该程序时会收到一下报错:

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

    错误提示的意思就是存在非ASCII字符,但是却没有encoding declared,同时给了一个连接并说明包含详细原因,这个链接是一个PEP(python enhancement proper)。
    enter image description here

    这个PEP的内容总结下来就是:
    这行代码用于声明代码文件的编码格式,这个信息可以帮助python解析器使用指定的正确编码来解释代码文件。这样就可以允许直接在代码中使用utf-8编码了。
    另外需要注意的是:声明的编码格式要和代码文件的格式一样才行,否则会报错。

    来看另外一个例子:

    # -*- coding:utf-8 -*-
    print('你好 python')
    

    将这段代码保存为ANSI格式,并执行,会得到以下报错:

    $ python ./hello_python.py
      File "./hello_python.py", line 2
    SyntaxError: (unicode error) 'utf-8' codec can't decode byte 0xc4 in position 0: invalid continuation byte
    

    所以说指定编码的时候也不能全部统一指定为utf-8,而是要根据源码文件的格式来指定,两者要一致才行。

    另外又在python的官方文档找到一个说明:
    enter image description here
    意思就是说:默认情况下,python解释器(python2)把源代码文件当做ASCII编码来处理,如果源码文件是其他格式就需要通过一个特殊的注释来说明,也就是:coding:utf-8,当然编码格式支持多中,具体看codecs的支持情况。
    这里其实也是由于python诞生的太早了,那时候Unicode都还没有诞生,因此当时作者也只能选择ASCII作为默认的编码格式。python3已经将默认编码格式改为UTF-8

    总结

    所以总结下来就是,python2中,该行代码的作用是当源代码文件不是ASCII编码时,通过该行代码告诉python解释器正确的编码格式,这样python解释器才能正常解释其中的字符。
    另外,由于python3已经修改为默认情况下,将源代码文件当做UTF-8格式来处理,同时我们写代码时现在通常都会使用UTF-8格式来存储,因此python3其实是不用再写这一行代码的,除非你的源代码文件不是UTF-8格式的。

    二、sys.setdefaultencoding('utf-8')

    先来看一个例子:

    # -*- coding:utf-8 -*-
    s = '你好'
    s.encode('gb2312')
    

    执行以上代码会收到下面的报错:

    Traceback (most recent call last):
      File "./hello_str.py", line 3, in <module>
        s.encode('gb2312')
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
    

    第一次遇到这个报错时,感觉很奇怪,明明我做的是encode操作,但是为什么报错确实decode失败呢?
    这里就是先提一下了:Python里面的编码和解码也就是unicode和str这两种形式的相互转化。编码是unicode->str,相反的,解码就是str->unicode。
    而上面定义的s是str类型的,因此当调用encode时,其实默认是先做了decode,转换为Unicode,然后再执行encode编码为指定的编码的,这里报错的原因就是当做隐式编码、解码时使用的默认格式是:ASCII,但是由于s是utf-8的编码,所以解码就失败了。
    解决办法:
    1、在文件头部添加sys.setdefaultencoding('utf-8')修改默认的编码、解码格式。

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

    2、避免由程序做隐式的编码、解码,也就是说要明确str-Unicode的转换规则,但是需要编码时要确认类型是Unicode,如果不是就手动指定正确的解码格式转换为Unicode。

    s.decode('utf-8').encode('gb2312')
    

    总结

    setdefaultencoding主要在编码、解码没有明确指明编码、解码格式的时候使用。

    三、参考资料

    1、PEP 263
    2、source-code-encoding

  • 相关阅读:
    cf D. Vessels
    cf C. Hamburgers
    zoj 3758 Singles' Day
    zoj 3777 Problem Arrangement
    zoj 3778 Talented Chef
    hdu 5087 Revenge of LIS II
    zoj 3785 What day is that day?
    zoj 3787 Access System
    判断给定图是否存在合法拓扑排序
    树-堆结构练习——合并果子之哈夫曼树
  • 原文地址:https://www.cnblogs.com/lit10050528/p/13290825.html
Copyright © 2011-2022 走看看