前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python--一文搞懂字符串的编解码

python--一文搞懂字符串的编解码

原创
作者头像
languageX
发布2023-05-04 00:15:07
1.3K0
发布2023-05-04 00:15:07
举报
文章被收录于专栏:计算机视觉CV计算机视觉CV

我们在使用python处理中文字符串时总会遇到一些问题,特别是一些老项目需要用到python2,中文显示乱码,文件读写异常等问题时常发生。

比如:

代码语言:javascript
复制
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

通常情况大家都是加上一个decode,encode解决问题,但是并没有完全搞清楚为什么。

本文就把python中的字符串处理一次性讲解清楚~

ASCII、Unicode和UTF-8的关系

由于计算机只能处理二进制,字符串类型必须转为数字才能处理,所以字符串是一种特殊的数据类型,它需要编解码才能在计算机中进行处理。

在最早计算机使用ASCII编码,只处理英文字母,数字和一些符号,所以127个字符就够了。

随着计算机发展,全世界各国语言都需要显示,ASCII码不够用了。Unicode编码应用而生,它把所有语言都统一编码。ASCII编码是1个字节,UniCode编码通常是2个字节。

但是英文字符明明1个字节就能搞定的事情,如果都统一使用UniCode,在空间上是一种浪费。所有又出现了UniCode的可变长编码形式UTF-8编码

UTF-8编码把UniCode字节根据不同的数字编码为1-6个字节,英文字母就是1个字节,中文汉字通常是3个字节。

在Python2中默认的编码是ASCII,不能识别中文字符,需要指定字符编码;

在Python3中默认的编码是Unicode,可以识别中文字符;

在计算节内存中,统一使用Unicode编码。

编码和解码

首先我们要区分下,字符串和字节码

Python的字符串类型是str,在内存中用Unicode表示,一个字符对应若干个字节。在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes也就是字节码。通常双引号或者单引号表示的,“中文”就是字符串,而b"中文"就是字节码。

Unicode编码字符串由str类型表示;二进制数据字节码由bytes类型表示。

文本编辑从文件读取的UTF-8字符会被转为Unicode字符存在内存里,处理完后,要保存的时候再把Unicode转为UTF-8保存。这里面就有编码和解码的过程。我们先了解什么是编码和解码。

编码(encode):将Unicode字符串转为特定编码格式对应的字节码的过程;就是将字符串转换为字节码

代码语言:javascript
复制
str.encode(encoding="utf-8", errors="strict")

表示将Unicode编码的字符串转为utf-8编码

解码(decode):将特定编码格式的字节码转为对应的Unicode字符串的过程;就是将字节码转换为字符串

代码语言:javascript
复制
bytes.decode(encoding="utf-8", errors="strict")

表示将utf8编码的字节码转为Unicode编码

在使用open读取文件后,read读取了字节码,这时候需要使用文本正确的编码格式进行解码decode为Unicode 。在write写文件时,则需要将Unicode编码encode为你希望的格式。

通常代码中我们通常会在文件开头添加如下代码:

代码语言:javascript
复制
#-*- coding: UTF-8 -*-

意思就是代码使用了UTF-8编码。

python2和python3

python2在读取文件后read(bytes.decode('文件编码格式'))进行一次解码;最后在写入时再write(txt.encode('写入编码格式'))将Unicode进行一次编码。

而在python3后,认为python2的方式太复杂了,每次还要自己转一下。所以将decode和encode作为参数放入了IO接口中,不需要手动指定编码解码了。

代码示例

下面我们使用代码来理解下上面介绍的内容。

我们在进行字符串操作时,首先要明确下环境的python版本,以及环境默认的编解码格式。

可以使用如下代码确认:

代码语言:javascript
复制
import sys
# 查看python版本
print(sys.version)
# 查看系统的编解码格式
# python2默认ASCII,python3默认UTF8
print(sys.getdefaultencoding())

在python2下运行

在python3下运行

在python2中ASCII码是不能显示中文的,我们可以设置代码使用utf8编码

代码语言:javascript
复制
reload(sys)
sys.setdefaultencoding('utf-8')

下面我们看下encode和decode用法:

代码语言:javascript
复制
'China'.encode('ascii')
输出:b'China'
'中国'.encode('utf-8')
输出:b'\xe4\xb8\xad\xe5\x9b\xbd'
'中国'.encode('ascii')
输出经典错误:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

以上错误就是因为含有中文的字符串是无法用ASCII编码。

代码语言:javascript
复制
"中国".decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'

以上错误是因为字符串没有decode。上文我们解释过,decode是将字节码解码为字符串,字符串是不能再解码的。同理b'\xe4\xb8\xad\xe6\x96\x87'字节码也没有encode方法。

代码语言:javascript
复制
b'\xe4\xb8\xad\xe6\x96\x87'.encode()
AttributeError: 'bytes' object has no attribute 'encode'

正确写法只有str.encode()和bytes.decode()

在操作字符串时,我们经常遇到str和bytes的互相转换。为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。

代码语言:javascript
复制
>>> str_a = u"中国"
>>> byte_b = str_a.encode("utf_8")
>>> str_u = byte_b.decode("utf_8")
>>> str_a == str_u
True

字符数和字节数:

代码语言:javascript
复制
>>> len("China")
5
>>> len("中文")
2
>>> len("China".encode("utf-8"))
5
>>> len("China".encode("ascii"))
5
>>> len("中文".encode("utf-8"))
6

1个英文字母和1个中文都是1个字符

但是1个英文字母只占1个字节,1个中文占3个字节~统计时不要混淆~

参考:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017075323632896

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ASCII、Unicode和UTF-8的关系
  • 编码和解码
  • python2和python3
  • 代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档