Python 字符编码理解

base: https://segmentfault.com/a/1190000007594453#articleHeader6

python获取默认编码

1
2
import sys
print(sys.getdefaultencoding())
  1. python3默认使用utf-8
  2. python2中默认使用ascii

python2中的字符类型

先插一张图讲解下python的类型
python2中字符串类型

归类

  1. python2中主要有两种字符串,一种为unicode,一种为str;
  2. unicode编码类,也就是以u开头的字符串,比如u’你好’,这类字符串使用unicode编码;
  3. unicode本身为将全世界所有语言统一的一套编码方案,由于存在很大的资源浪费,所有编码时并不一定会使用unicode
  4. str的实现方式有utf-8,ascii等,这些都是unicode的具体实现方式。
  5. unicode字符串通过encode函数转换为str,str通过decode转换为unicode

UnicodeEncodeError和UnicodeDecodeError

在进行同时包含 str 类型和 unicode 类型的字符串操作时,Python2 一律都把 str 解码(decode)成 unicode 再运算,这时就很容易出现 UnicodeDecodeError。

例子1

1
2
3
4
5
6
>>> s = '你好'    # str 类型, utf-8 编码
>>> u = u'世界' # unicode 类型
>>> s + u # 会进行隐式转换,即 s.decode('ascii') + u
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

出错的原因是:

  1. 同时对str和unicode字符串进行操作,python会将str转换为unicode;
  2. 由于python2默认使用ascii进行编码,而s是使用utf-8进行编码的,所以在将s转换为unicode时,默认使用ascii转换,此时会失败;

修改为s.decode('utf-8') + u就不会报错了

我的理解

  1. unicode是全世界统一的字符串编码,由于存在资源浪费,所以python使用str作为具体使用的字符串编码;
  2. 当我们在python中定义一个字符串时,python会自动处理将其进行编码,如中文处理为utf-8的str对象;
  3. 但是str对象中不包含编码信息,所以python2会自动以ascii处理str对象;
  4. 即使我们在python源文件中定义了默认的编码方式为utf-8,python解释器也会照样使用ascii为默认编码encode/decode编码方式
    第四点观点通过以下测试文件验证:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/usr/bin/env python
    # encoding: utf-8


    s1 = '查看系统'
    s2 = u'内所有安装'

    print s1
    print s2
    print s1.decode('utf-8') + s2
    print s1 + s2 # this line will raise error
0%