杰瑞科技汇

Python列表如何处理Unicode数据?

核心要点

  1. Python 3 的默认编码是 Unicode:这是最关键的一点,从 Python 3 开始,字符串(str)类型在内存中默认就是以 Unicode 编码存储的,你不需要做任何特殊设置,就可以直接在代码中写入中文、日文等。
  2. 列表可以存储任何类型的数据:列表可以存储整数、浮点数、布尔值,当然也包括 Unicode 字符串。
  3. 编码 vs. 解码:当你的 Python 程序需要与外部世界交互时(将字符串写入文件、通过网络发送、在控制台打印),就需要考虑编码问题。
    • 编码:将 Unicode 字符串(str)转换成字节序列(bytes),以便存储或传输。
    • 解码:将字节序列(bytes)转换回 Unicode 字符串(str),以便程序处理。

在 Python 3 中创建包含 Unicode 字符串的列表

在 Python 3 中,直接写字符串字面量,它就是 Unicode 字符串。

Python列表如何处理Unicode数据?-图1
(图片来源网络,侵删)
# 创建一个包含多种语言的列表
my_unicode_list = [
    "你好,世界!",      # 中文
    "こんにちは",       # 日文
    "안녕하세요",       # 韩文
    "Hello, World!",   # 英文
    "😊"              # 表情符号 (也是 Unicode 字符)
]
# 访问列表中的元素
print(my_unicode_list[0])  # 输出: 你好,世界!
print(my_unicode_list[4])  # 输出: 😊
# 遍历列表
for item in my_unicode_list:
    print(item)

输出:

你好,世界!
こんにちは
안녕하세요
Hello, World!
😊
你好,世界!
こんにちは
안녕하세요
Hello, World!
😊

你会发现,这一切都非常自然,没有出现任何乱码,这是因为 Python 3 内部已经帮你处理好了。


编码与解码:当列表需要“离开”Python 内存时

当你需要将列表中的字符串保存到文件或发送到网络时,就必须进行编码,因为文件和网络的底层只能处理二进制数据(bytes)。

将列表写入文件

假设我们想把上面的 my_unicode_list 写入一个名为 data.txt 的文件。

Python列表如何处理Unicode数据?-图2
(图片来源网络,侵删)

错误的做法(会引发 TypeError

my_unicode_list = ["你好", "世界"]
# 尝试直接将字符串列表写入二进制模式文件会报错
with open('data.txt', 'wb') as f: # 'wb' 表示以二进制写入模式打开
    f.write(my_unicode_list) # TypeError: write() argument must be str, not list

即使我们修复 list 的问题,直接写一个字符串也会报错:

my_unicode_list = ["你好", "世界"]
# 尝试将字符串写入二进制模式文件也会报错
with open('data.txt', 'wb') as f:
    f.write(my_unicode_list[0]) # TypeError: a bytes-like object is required, not 'str'

这个错误提示很明确:'wb' 模式需要 bytes 对象,但你给了它一个 str 对象。

正确的做法:先编码,再写入

Python列表如何处理Unicode数据?-图3
(图片来源网络,侵删)

我们需要先将列表中的每个字符串元素编码成 bytes

my_unicode_list = ["你好", "世界"]
# 1. 定义一个编码,通常推荐使用 'utf-8',因为它能表示所有 Unicode 字符
encoding_type = 'utf-8'
# 2. 将列表中的每个字符串编码成 bytes,并创建一个新列表
bytes_list = [s.encode(encoding_type) for s in my_unicode_list]
# 3. 将 bytes_list 写入文件(使用 'wb' 模式)
with open('data.txt', 'wb') as f:
    for line in bytes_list:
        f.write(line)
        f.write(b'\n') # 写入换行符,bytes 类型的换行符是 b'\n'
print("数据已成功写入 data.txt")

验证:读取文件时需要解码

我们读取这个文件时,需要从 bytes 解码回 str

# 1. 以二进制模式 ('rb') 读取文件,得到的是 bytes 对象
with open('data.txt', 'rb') as f:
    lines_from_file = f.readlines()
# 2. 将每一行 bytes 解码回 str
decoded_list = [line.strip().decode(encoding_type) for line in lines_from_file]
print("从文件读取并解码后的列表:")
print(decoded_list)

输出:

从文件读取并解码后的列表:
['你好', '世界']

可以看到,数据完美地保存和恢复了。


常见的编码问题

问题1:使用了错误的编码

如果你在编码时使用 gbk(一种主要用于简体中文的编码),而你的字符串里包含了日文或表情符号,程序就会抛出 UnicodeEncodeError

my_unicode_list = ["你好", "こんにちは"]
# 尝试用 'gbk' 编码包含日文的字符串
try:
    encoded_bytes = "こんにちは".encode('gbk')
except UnicodeEncodeError as e:
    print(f"编码错误: {e}")
    # 输出: 编码错误: 'gbk' codec can't encode character '\u3053' in position 0: illegal multibyte sequence

解决方案:始终使用 utf-8 除非你有特殊需求(比如与一个只支持 gbk 的旧系统交互)。

问题2:读取文件时使用了错误的编码

如果你用 utf-8 去读取一个用 gbk 编码的文件,你会得到 UnicodeDecodeError

假设 data_gbk.txt 文件是用 gbk 编码保存的 "你好"。

# 假设 data_gbk.txt 是用 'gbk' 编码保存的 "你好"
# 尝试用 'utf-8' 去解码
try:
    with open('data_gbk.txt', 'rb') as f:
        content = f.read().decode('utf-8')
except UnicodeDecodeError as e:
    print(f"解码错误: {e}")
    # 输出: 解码错误: 'utf-8' codec can't decode byte 0xc4 in position 0: invalid start byte

解决方案:你需要知道文件的原始编码,并使用相同的编码来解码。


总结与最佳实践

  1. Python 3 内部是 Unicode:在程序内部处理字符串时,你无需担心编码问题,直接使用 str 类型即可。
  2. 列表存储 Unicode 字符串:列表可以无缝地存储各种语言的 Unicode 字符串。
  3. I/O 操作需要编码:当涉及文件读写、网络请求等与外部交互的操作时,必须进行编码和解码。
    • 写入str -> .encode('utf-8') -> bytes -> 写入文件/网络
    • 读取:从文件/网络读取 -> bytes -> .decode('utf-8') -> str
  4. 统一使用 UTF-8:在不确定的情况下,utf-8 是最安全、最现代的选择,它能表示地球上几乎所有的字符,并且是事实上的标准。
  5. 处理异常:在编码和解码时,最好使用 try...except 块来捕获 UnicodeEncodeErrorUnicodeDecodeError,让你的程序更健壮。
分享:
扫描分享到社交APP
上一篇
下一篇