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

    几个编码概念

    1. 脚本字符编码: 指定python脚本中字符的编码方式(python在处理数据时,以什么编码方式来处理)

      • python2: ASCII
      • python3: UTF-8
    2. 解释器字符编码: python解释器默认的编码方式

      • python2: ASCII
      • python3: UTF-8
    3. 系统编码: 这个编码和python本身没有太大关系,只是我们有时候会看到乱码情况,这时就和系统编码有关

    几类常见的问题

    1. SyntaxError: Non-ASCII character 'xe5' in file...

      这一类问题一般出现在python2中,由脚本字符编码导致。当脚本中出现中文,且未指定编码类型,那么python2在处理脚本数据时,会用默认的ASCII去解析中文,导致上面的error。

      python2的脚本文件,一般都会说明字符编码类型,如#-*- encoding: utf-8 -*-

      详情: http://python.org/dev/peps/pep-0263/

    2. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

      这类问题一般出现在python2中,在编码类型转换中触发。

      python2中有两个编解码函数: decodeencode,用于unicode编码和其他编码方式的转换。 decode将其他编码类型的字符串,转化为unicode编码,反之, encode将unicode编码转换为其他. 我们可以通过这两个函数,获取某种编码下的变量值,如:

      >>> import chardet
      >>> a = '张三'  
      >>> chardet.detect(a)
      {'confidence': 0.7525, 'language': '', 'encoding': 'utf-8'}    # 系统默认编码为utf-8, 所以a的编码为utf-8
      >>> b = a.decode('utf-8')     # 用utf-8 解码后,得到unicode字符串
      >>> b
      u'u5f20u4e09'
      >>> c = b.encode('gb2312')    # 将unicode 编码为gbk
      >>> chardet.detect(c)
      {'confidence': 0.682639754276994, 'language': 'Russian', 'encoding': 'KOI8-R'}
      
      >>> chardet.detect(a.decode('utf-8').encode('gb2312'))   # 一次性变更有同样的效果
      {'confidence': 0.682639754276994, 'language': 'Russian', 'encoding': 'KOI8-R'}
      

      但是,当由于某种原因,我们无意将一种非unicode编码,转换为另一种非unicode编码,且未指定解码方式时,可能出现上述error,如

      >>> a.encode('gb2312')   # a是utf-8编码,强行转换成gb2312,会出错
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
      

      这是因为,如果a不是unicode编码,且要转换成另外一种编码的情况下,python会用默认的解释器编码先进行解码,即进行a.decode('ascii')的操作,但是由于a中包含中文,ascii无法解析,故报错

    3. 乱码问题。

      乱码不是python自身的问题,而是和第三方系统相关,即变量的编码类型,和显示系统的编码类型不一致,会造成乱码。简单举个例子:

      此刻我使用的macos,系统默认编码为utf-8

      >>> a = '李四'
      >>> chardet.detect(a)
      {'confidence': 0.7525, 'language': '', 'encoding': 'utf-8'}
      >>> print(a)
      李四
      >>> b = a.decode('utf-8').encode('gbk')
      >>> print(b)
      ����
      >>>
      

    python3中对编码问题的优化

    1. 脚本中的字符不再受系统默认编码的影响,统一为unicode

      ➜ ~ python2	
      Python 2.7.16 (default, Feb 29 2020, 01:55:37)
      [GCC 4.2.1 Compatible Apple LLVM 11.0.3 (clang-1103.0.29.20) (-macos10.15-objc- on darwin
      Type "help", "copyright", "credits" or "license" for more information.
      >>>
      >>> import chardet
      >>> a = '张三'
      >>> chardet.detect(a)
      {'confidence': 0.7525, 'language': '', 'encoding': 'utf-8'}
      

      可以看到,在python2中,字符的默认编码是和系统默认编码保持一致的
      特别注意: 字符默认编码和# -*- encoding=xxx -*-的声明没有关系,该声明只是告诉python解释器应该用什么编码方式去读取脚本内容

      ➜  ~ python3
      Python 3.7.3 (default, Sep 18 2019, 14:29:06)
      [Clang 11.0.0 (clang-1100.0.33.8)] on darwin
      Type "help", "copyright", "credits" or "license" for more information.
      >>>
      >>> import chardet
      >>> a = '张三'
      >>> chardet.detect(a)      # chardet的参数必须是字节流,python3中字符默认unicode,所以报错
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Library/Python/3.7/site-packages/chardet/__init__.py", line 34, in detect
      '{0}'.format(type(byte_str)))
      TypeError: Expected object of type bytes or bytearray, got: <class 'str'>
      >>> type(a)
      <class 'str'>              # python3中使用str表示unicode
      

      可以看到,python3中,字符的默认编码是str(也就是py2中的unicode),不再受系统默认编码影响

    2. 脚本默认编码方式为utf-8, 即不必在脚本开头声明# -*- encoding: utf-8 -*-,也可以在脚本中随意使用中文

    3. 将字符串和字节序列做了区分。增加了bytes数据类型。

      字符串str: 对标python2中的unicode

      >>> a = '李四'
      >>> type(a)
      <class 'str'> 
      

      比如,a的默认类型即为str类

      bytes: 对标python2中str类型(包含各种编码方式)

      >>> b = a.encode('utf-8')
      >>> type(b)
      <class 'bytes'>
      >>> chardet.detect(b)
      {'encoding': 'utf-8', 'confidence': 0.7525, 'language': ''}
      
      >>> type(a.encode('gbk'))
      <class 'bytes'>
      
  • 相关阅读:
    Python之数据类型
    Python之变量
    第01组Alpha冲刺总结
    第01组 Alpha冲刺(6/6)
    第01组 Alpha冲刺(5/6)
    第01组 Alpha冲刺(4/6)
    第01组 Alpha冲刺(3/6)
    第01组 Alpha冲刺(2/6)
    第01组 Alpha冲刺 (1/6)
    第01组(17) 需求分析报告
  • 原文地址:https://www.cnblogs.com/liushi-Oscar/p/12901937.html
Copyright © 2011-2022 走看看