如果你用 Python 写程序,只要和程序打交道(比如处理文本、接口、文件、网页),几乎绕不开「字符串」和「编码」。特别是当你看到 UnicodeEncodeError
或 UnicodeDecodeError
报错时,那种「我做错了什么」的无助感,你懂的。
所以这篇文章我们就来一次性理清楚:
str
是文本,bytes
是字节Python3 中有两个跟「字符串」相关的类型:
s = "你好,world" # str 类型
b = b"hello" # bytes 类型
类型 | 内容 | 举例 |
---|---|---|
str | 文本(字符) | "你好abc" |
bytes | 字节(数字) | b"\xe4\xbd\xa0" |
重点记住:
str
是给人看的
bytes
是给计算机传输和存储的
>>> b"hello" + "世界"
TypeError: can't concat str to bytes
要么编码,要么解码。
就是把 str(字符)→ 转换成 bytes(字节)
"你好".encode("utf-8")
# 输出:b'\xe4\xbd\xa0\xe5\xa5\xbd'
就是把 bytes(字节)→ 转换成 str(字符)
b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode("utf-8")
# 输出:'你好'
编码方式 | 特点 |
---|---|
UTF-8 | 推荐!通用、网页都用它 |
GBK | 中文系统默认,老系统多见 |
ASCII | 英文和数字,最基础 |
UTF-16 | 占空间,通常不用 |
乱码 = 解码方式 ≠ 编码方式
举个例子:
text = "你好"
b = text.encode("utf-8")
print(b.decode("gbk")) # 这就乱码了
所以你要记住这句话:编码用什么,解码就用什么!
isinstance(obj, str) # 是文本?
isinstance(obj, bytes) # 是字节?
"你好".encode("utf-8").decode("utf-8")
"你好".encode("utf-8", errors="ignore")
"你好".encode("utf-8", errors="replace")
可以避免一些编码错误爆炸。
with open("file.txt", encoding="utf-8") as f:
content = f.read()
import requests
r = requests.get("https://example.com")
html = r.content.decode("utf-8")
用 .decode("utf-8")
转一下。
问题 | 原因 | 解决方案 |
---|---|---|
文件读出来是乱码 | 文件本身是 GBK,你用 utf-8 读了 | open(..., encoding="gbk") |
API 返回中文乱码 | 服务端编码是 GBK 或未声明 | 尝试 response.content.decode(...) |
打印日志时报 encode 错误 | 控制台编码与程序编码不一致 | 用 encode(errors="replace") |
bytes 和 str 混用报错 | Python 不允许 str + bytes 拼接 | 明确转换为统一格式 |
str
和 bytes
分得很清楚了。
str
实际是 Unicode 编码。
len(s)
有时不等于实际字节长度:
>>> len("你好") # 是字符数
2
>>> len("你好".encode("utf-8")) # 是字节数
6
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。