当前位置: 首页 > 后端技术 > Python

有了这篇文章, Python 中的编码不再是噩梦

时间:2023-03-26 19:42:30 Python

得益于这篇Github文章,使用Python编码不再是噩梦:https://github.com/iswbm/Pyth...Python编码问题一直是许多Python开发人员的噩梦。即使你是工作多年的Python开发者,也一定会遇到烦人的编码问题,花了很长时间才搞清楚。过了一段时间,你又忘记了一切,你开始寻找各种博客和帖子,从头弄清楚什么是编码?什么是单码?它与ASCII码有何不同?为什么decodeencode总是报错?为什么python2和python3中的字符串类型不同,又是如何对应的呢?如何检测编码格式?一遍又一遍,这个过程真的很痛苦。今天给大家讲解了一些大家在Python上都会遇到的编码问题。以后不用谷歌就可以保存这篇文章。1.Python3中的str和bytes在Python3中,有两种类型的字符串,str和bytes。今天说说两者的区别:unicodestring(str类型):以Unicode码点的形式存储,人类识别的形式bytestring(bytes类型):以byte的形式存储,人类识别的形式machineinPython3你定义的所有字符串都是unicode字符串类型,可以通过type和isinstance来识别#python3>>>str_obj="Hello">>>>>>type(str_obj)>>>>>>isinstance("Hello",str)True>>>>>>isinstance("Hello",bytes)False>>>bytes是二进制序列对象,只需要在前面加一个定义字符串b,表示要定义一个bytes类型的字符串对象。#python3>>>byte_obj=b"HelloWorld!">>>type(byte_obj)>>>>>>isinstance(byte_obj,str)False>>>>>>isinstance(byte_obj,bytes)True>>>但是当定义一个中文字符串时,你前面不能直接加b,要用encode转换一下。>>>byte_obj=b"Hello"File"",line1SyntaxError:bytescanonlycontainASCIIliteralcharacters.>>>>>>str_obj="Hello">>>>>>str_obj.encode("utf-8")b'\xe4\xbd\xa0\xe5\xa5\xbd'>>>2.在Python2中,str和unicode,但是在Python2中,string的类型和Python3不同,需要仔细区分。在Python2中,字符串只有unicode和str两种类型。仅unicode对象和非unicode对象的区别(其实应该叫str对象):unicode字符串(unicode类型):以Unicode码点的形式存储,人类识别的字节串形式(str类型):以字节形式存储,机器识别的形式当我们直接用双引号或者单引号定义一个字符串时,就是一个str字符串对象,比如这个#python2>>>str_obj="Hello">>>>>>type(str_obj)>>>>>>str_obj'\xe4\xbd\xa0\xe5\xa5\xbd'>>>>>>isinstance(str_obj,bytes)True>>>isinstance(str_obj,str)True>>>isinstance(str_obj,unicode)False>>>>>>strisbytesTrue当我们在双引号或单引号前加一个u时,表示我们定义了一个unicode字符串对象,比如这个#python2>>>unicode_obj=u"Hello">>>>>>unicode_obju'\u4f60\u597d'>>>>>>type(unicode_obj)>>>>>>isinstance(unicode_obj,bytes)False>>>isinstance(unicode_obj,str)False>>>>>>isinstance(unicode_obj,unicode)True3。如何检测对象的编码所有字符在unicode字符集中都有对应的编码值(英文名称:codepoint)并将这些编码后的值按照一定的规则保存成二进制字节码,也就是我们所说的编码方式。常见的有:UTF-8、GB2312等。也就是说,当我们要将内存中的字符串持久化到硬盘中时,必须指定编码方式,反之,读取时,正确的编码方式也必须指定(这个过程称为解码),否则会出现乱码。那么问题来了,当我们知道了对应的编码方式后,就可以正常解码了,但是并不是每时每刻都能知道应该用什么编码方式来解码呢?这时候我们就来介绍一个python库——chardet。使用前需要安装python3-mpipinstallchardetchardet有个检测方法,可以预测它的编码格式>>>importchardet>>>chardet.detect('微信公众号:Python编程时间'.encode('gbk')){'encoding':'GB2312','confidence':0.99,'language':'Chinese'}为什么是预测呢?通过上面的输出来看,会看到有一个confidence字段,表示预测的可靠性,或者说成功率。但是在使用的时候,如果你的字符数少,可能会被“误诊”),比如中文只有两个字符,如下图,我们使用的是gbk编码,但是使用chardet识别为KOI8-R编码。>>>str_obj="Chinese">>>byte_obj=bytes(a,encoding='gbk')#首先得到一个gbk编码的字节>>>>>>chardet.detect(byte_obj){'encoding':'KOI8-R','confidence':0.682639754276994,'language':'Russian'}>>>>>>str_obj2=str(byte_obj,encoding='KOI8-R')>>>str_obj2'жпнд'所以编码诊断要准确地说,尽量使用尽可能多的字符。Chardet支持多种语言。从官方文档可以看出它支持以下语言(https://chardet.readthedocs.i...4.编码和解码的区别编码和解码其实就是str和bytes相互转换的过程(Python2没了,这里以后只以Python3为例)Encoding:encode方法,将string对象转为二进制字节序列Decoding:decode方法,将二进制字节序列转为string对象那么如果我们真的知道它的编码格式,怎么转成unicode呢,有两种方法,第一种是直接使用decode方法>>>byte_obj.decode('gbk')'Chinese'>>>第二种是,使用str类转>>>str_obj=str(byte_obj,encoding='gbk')>>>str_obj'Chinese'>>>5.如何设置文件编码在Python2中,默认是ASCII编码来读取的,因此,我们在使用Python时2、如果你的python文件中有中文,运行会报错SyntaxError:Non-ASCIIcharacter'\xe4'in文件demo.py原因是ASCII码表太小,无法解释中文。在Python3中,默认使用uft-8来读取,这样就省去了很多麻烦。对于这个问题,通常有两种解决方法:第一种方法在python2中,可以在header中使用,指定可以这样写,虽然看起来不错#-*-coding:utf-8-*-但是这样写太麻烦了,我一般用下面两种写法#coding:utf-8#coding=utf-8第二种方法importsysreload(sys)sys.setdefaultencoding('utf-8')这里在调用sys.setdefaultencoding('utf-8')设置默认解码方式之前,执行reload(sys),这个是必须的,因为python加载sys后会删除sys.setdefaultencoding方法,我们需要重新加载sys才能调用sys.setdefaultencoding这种方式。