python 中文乱码问题深入分析

  • Post category:Python

Python 中文乱码问题深入分析

问题背景

在 Python 中处理中文字符串时,经常会遇到中文乱码问题,在输出、读写文件、网络传输等场景中可能会出现。

例如,在 Python 2.x 版本下:

>>> s = '你好'
>>> print s
???   # 输出了乱码

在 Python 3.x 版本下:

>>> s = '你好'
>>> print(s)
你好

可以看到,在 Python 2.x 版本下输出了乱码,在 Python 3.x 版本下输出了正确的中文字符串。下面我们来深入分析这个问题。

分析过程

字符编码的概念

在分析中文乱码问题前,首先要了解字符编码的概念。字符编码就是将字符转换为计算机可以理解并处理的二进制数据的规则,不同的编码标准对应不同的二进制数据。

常见的中文字符编码有 GB2312、GBK、GB18030、UTF-8 等。

Python 中的字符编码问题

在 Python 2.x 版本下,字符串默认使用的是 ASCII 码编码,对于非 ASCII 码字符(例如中文字符)则需要使用其他编码方式进行处理。

而在 Python 3.x 版本下,字符串默认使用的是 Unicode 编码,可以直接处理多字符集。

因此,在 Python 2.x 版本下处理中文字符串时,经常需要考虑字符编码的问题,而在 Python 3.x 版本下则相对简单。

处理中文乱码问题的方法

1. 在 Python 2.x 版本下

在 Python 2.x 版本下,处理中文乱码问题可以采用以下方法:

(1)在文件开头添加编码声明

可以在 Python 2.x 版本的代码文件开头添加如下代码:

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

这行代码可以告诉 Python 使用 utf-8 编码方式处理该文件中的字符串,避免出现中文乱码。

(2)使用 Unicode 字符串

可以将中文字符串转换为 Unicode 字符串进行处理,例如:

>>> s = u'你好'
>>> print s
你好

这里的 u 前缀表示将字符串转换为 Unicode 字符串。

2. 在 Python 3.x 版本下

在 Python 3.x 版本下,默认使用 Unicode 编码,因此可以直接处理多字符集。不过需要注意,在输出到终端或者进行网络传输时,要进行编码转换,例如:

>>> s = '你好'
>>> b = s.encode('utf-8')
>>> print(b)
b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print(b.decode('utf-8'))
你好

这里将字符串 s 转换为 utf-8 编码的 bytes 对象 b,然后再进行解码,输出正确的中文字符串。

示例说明

示例一:读写文件时出现中文乱码

考虑以下 Python 2.x 版本下的代码:

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

f = open('test.txt', 'w')
str = '你好'
f.write(str)
f.close()

f = open('test.txt', 'r')
print f.read()
f.close()

这里打开 test.txt 文件,写入中文字符串 str,然后再读取并输出该文件内容。但是,由于没有进行编码转换,输出结果出现了中文乱码。

可以通过在文件开头添加编码声明的方式解决这个问题,代码修改为:

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

f = open('test.txt', 'w')
str = u'你好'
f.write(str.encode('utf-8'))
f.close()

f = open('test.txt', 'r')
print f.read().decode('utf-8')
f.close()

这里将中文字符串 str 转换为 Unicode 字符串,并使用 utf-8 编码方式写入文件。读取文件时,先将内容读取为 bytes 对象,再进行解码,输出正确的中文字符串。

示例二:字符串序列化时出现中文乱码

考虑以下 Python 2.x 版本下的代码:

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

import json

data = {
    'name': '张三',
    'age': 18
}

s = json.dumps(data)
print s

d = json.loads(s)
print d

这里使用 Python 自带的 json 模块将字典对象序列化为字符串,并输出该字符串。但是由于该字符串中包含中文字符,输出结果出现了中文乱码。

可以通过将中文字符串转换为 Unicode 字符串的方式解决这个问题,代码修改为:

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

import json

data = {
    'name': u'张三',
    'age': 18
}

s = json.dumps(data, ensure_ascii=False)
print s

d = json.loads(s)
print d

这里将中文字符串 张三 转换为 Unicode 字符串。将 ensure_ascii 参数设为 False 以表示输出非 ASCII 码字符。这样就可以正确输出中文字符串了。

总结

在 Python 中处理中文字符串时,需要考虑字符编码的问题。在 Python 2.x 版本下,需要进行编码转换;而在 Python 3.x 版本下则相对简单。处理中文乱码问题的方法包括在文件开头添加编码声明、使用 Unicode 字符串、进行编码转换等。