python--字符/文本编码解码笔记
字符/文本编码解码笔记
- 1.字符问题
- 编码和解码
- 2.字节概要
- 3.基本的编解码器
- 编码类型史
- 字符编码
- ASCII码
- GB2312以及其他编码
- UNICODE标准编码
- UTF-8编码
- 4.了解编解码问题
- 处理UnicodeEncoderError
- 解决方法:
- 处理UnicodeDecodeError
- 解决方法
- 5.修改源代码编码
- 6.查看文件编码方式
- 终端查看文件编码方式
- 代码内查看文件编码方式
- 7.处理文本文件
- 查看open函数默认编码方式
1.字符问题
“字符串”是个相当简单的概念:一个字符串是一个字符序列。
在 2015 年,“字符”的最佳定义是 Unicode 字符。因此,从 Python 3 的 str
对象中获取的元素是 Unicode 字符。但是Python 3 默认使用 UTF-8 编码源码。注意区分。
Unicode 标准把字符的标识和具体的字节表述进行了如下的明确区分。
- 字符的标识,即码位,是 0~1 114 111 的数字(十进制),在 Unicode 标准中以 4~6 个十六进制数字表示,而且加前缀“U+”。例如,字母 A 的码位是 U+0041。
- 字符的具体表述取决于所用的编码,也就是除了Unicode以外其他编码的表示。编码是在码位和字节序列之间转换时使用的算法。比如在 UTF-8 编码中,A(U+0041)的码位编码成单个字节 \x41。一个字符串则编码为由多个字节组成的字节序列。后面会多处提到字节序列,把它当成用其他编码器对Unicode字符编码的结果就可以了。
编码和解码
编码是把码位转换成字节序列的过程。通俗的讲就是将Unicode编码的字符转化为其他编码的字符。
解码是把字节序列转换成码位的过程。通俗的讲就是将其他编码的字符转化为Unicode编码的字符。
s='sabér'
print(s)
print(len(s)) #1
b=s.encode('utf-8') #2
print(b) #3
print(len(b)) #4
x=b.decode('utf-8')#5
print(x)
输出:
sabér
5
b'sab\xc3\xa9r'
6
sabér
- 1.
'sabér'
字符串有5个Unicode字符。 - 2.使用UTF-8把
str
对象编码成bytes
对象。 - 3.
bytes
字面量以b开头,表示字节序列。 - 4.字节序列 b 有 5 个字节(在 UTF-8 中,“é”的码位编码成两个字节)。
- 5.使用 UTF-8 把
bytes
对象(字节对象)解码成str
对象。
由于Unicode编码是标准编码格式,也可以看做是没有任何特定编码格式的“无编码”模式。所以,对于任何Unicode类型编码的字符,打印时python会自动根据环境编码转为特定编码后再显示,Python 3 为所有平台设置的默认编码都是 UTF-8。
2.字节概要
Python 内置了两种基本的二进制序列类型:不可变 bytes
类型和 可变 bytearray
类型。
3.基本的编解码器
Python 自带了超过 100 种编解码器(codec, encoder/decoder),用于在文本和字节之间相 互转换。每个编解码器都有一个名称,如 ‘utf_8’,而且经常有几个别名,如 ‘utf8’、‘utf-8’ 和 ‘U8’。
- 上图有12个字符,code point表示其码位,还有7种编码的字节表述(十六进制)。
- 星号表明,某些编码(如 ASCII 和多字节的 GB2312)不能表示所有 Unicode 字符。然而,UTF 编码的设计目的就是处理每一个 Unicode 码位。
编码类型史
字符编码
将人类语言转化为计算机能够理解的二进制的数(0,1),我们用bit(位)来表示,通常转化的时候是按byte(字节)来处理,一个字节等于8bit。
ASCII码
ASCII码是人类计算机历史上最早发明的字符集,ASCII码是专门为表示英文、数字以及英文标点符号而生。ASCII编码使用一个字节编码,一个字节有256种组合,足够存储这些字符。
GB2312以及其他编码
由于中文汉字非常多,ASCII无法满足汉字存储的需求。
为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为GB码,或国标码。
其中最有影响的是于1980年发布的《信息交换用汉字编码字符集 基本集》,标准号为GB 2312-1980,因其使用非常普遍,也常被通称为国标码。GB2312编码通行于我国内地;新加坡等地也采用此编码。几乎所有的中文系统和国际化的软件都支持GB 2312。
所以,大家可以理解为,GB系列的编码是为了适应复杂的中文编码而对ASCII码的一种扩充。
UNICODE标准编码
每个国家都会对ASCII码扩展出自己的一套编码,就存在不同编码之间的转换和显示问题。为了解决这个问题,需要一套统一的编码格式,即Unicode。
Unicode又被称为统一码、万国码;它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
Unicode编码通常由两个字节组成,共表示256*256个字符,即所谓的UCS-2。某些偏僻字还会用到四个字节,即所谓的UCS-4。
并且Unicode兼容ASCII,在Unicode中,原本ASCII中的127个字符只需在前面补一个全零的字节即可。
UTF-8编码
UNICODE编码有个缺点,所有语言的字符都是固定长度的存储,有些语言的字符只需占用少量的存储空间,这就导致浪费了大量的存储空间。
为了解决这个问题,就出现了一些中间格式的字符集,他们被称为通用转换格式,即UTF(Unicode Transformation Format)。
我们最常用的UTF-8就是这些转换格式中的一种。UTF-8编码其实是一种可“变长”的编码格式,即把英文变长为1个字节,而汉字用3个字节表示,特别生僻的还会变成4-6字节。
该部分参考:一文搞懂Python字符编码问题
4.了解编解码问题
虽然有个一般性的 UnicodeError 异常,但是报告错误时几乎都会指明具体的异常:UnicodeEncodeError(把字符串转换成二进制序列时)或 UnicodeDecodeError(把二进制序列转换成字符串时)。如果源码的编码与预期不符, 加载 Python 模块时还可能抛出 SyntaxError。
处理UnicodeEncoderError
多数非 UTF 编解码器只能处理 Unicode 字符的一小部分子集。把文本(Unicode 字符)转换成字节序列时,如果目标编码中没有定义某个字符,那就会抛出 UnicodeEncodeError 异常。
解决方法:
- 1.在encode()函数中添加参数error,举例如下:
city = 'São Paulo'
x=city.encode('cp437', errors='ignore')
print(x)
y=city.encode('cp437', errors='replace')
print(y)
z=city.encode('cp437', errors='xmlcharrefreplace')
print(z)
输出:
b'So Paulo'
b'S?o Paulo'
b'São Paulo'
error=‘ignore’ 处理方式悄无声息地跳过无法编码的字符;
error='replace’把无法编码的字符替换成 ‘?’;
error=‘xmlcharrefreplace’ 把无法编码的字符替换成 XML实体。
以上解决是十分不妥的,损坏了数据。
编解码器的错误处理方式是可扩展的。你可以为 errors 参数注册额外的字符串,方法是把一个名称和一个错误处理函数传给 codecs.register_error 函数。 参见 codecs.register_error 函数的官方文档。
- 2.换一种编码器,尽量使用UTF-8编码器。
处理UnicodeDecodeError
ASCII字符有127个,但是一个字节表示的空间有256个。所以不是每一个字节都包含有效的 ASCII 字符。
同理,不是每一个字符序列都是有效的 UTF-8 或 UTF-16。
把二进制序列(字节序列)转换成文本(Unicode字符)时,如果字节序列有无效的字节时,遇到无法转换的字节序列时会抛出 UnicodeDecodeError。
举例如下:
octets = b'Montr\xe9al'
oct=octets.decode('cp1252')
print(oct)
oct1=octets.decode('utf_8')
print(oct1)
oct2=octets.decode('utf_8', errors='replace')
print(oct2)
输出:
Montréal
Traceback (most recent call last):File "c:\Users\13451\Desktop\python基本操作\1.py", line 18, in <module>oct1=octets.decode('utf_8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte
'Montral'
- 这些字节序列是使用 latin1 编码的“Montréal”;’\xe9’ 字节对应“é”。
- 可以使用 ‘cp1252’(Windows 1252)解码,因为它是 latin1 的有效超集。
- ‘utf_8’ 编解码器检测到 octets 不是有效的 UTF-8 字符串,抛出 UnicodeDecodeError。bug中position从零开始数。
解决方法
使用 ‘replace’ 错误处理方式,\xe9 替换成了替换字符(码位是 U+FFFD),这是官方指定的 REPLACEMENT CHARACTER(替换字符),表示未知字符。替换字符:形状为黑色菱形,且中间填充了一个问号。
5.修改源代码编码
Python 3 默认使用 UTF-8 编码源码且Python 3 为所有平台设置的默认编码都是 UTF-8。
在源代码第一行加# coding: cp1252
即可用cp1252编码,或者编辑器或IDE都有更改编码的途径。
6.查看文件编码方式
终端查看文件编码方式
安装统一字符编码侦测包 Chardet。
终端使用:
chardetect 1.py
输出:
1.py: utf-8 with confidence 0.99
表示1.py有0.99的可能是utf-8编码。
代码内查看文件编码方式
使用chardet
库的detect
函数
import chardet
file1='data/test.txt'
f=open(file1,'rb')
f_encoding=chardet.detect(f.read())
print(f_encoding)
f.close()
输出:
{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
7.处理文本文件
使用open()函数打开文件,有两种方式处理文件:文本模式和二进制模式。
添加encoding
参数可以设置编码方式,这个编码方式在编码输出文本的时候会用到,即下图第三行。open()函数默认采用文本模式。默认编码方式取决于平台,window10下为gbk,linux下为utf-8。当处于二进制模式时不能添加encoding参数,因为本身就是二进制了,不需要再编码。
- 如果调用read()函数,open 函数会在读取文件时做必要的解码(自动解码成Unicode字符,即str)。对应下图解码输入的字节序列,得到
str
对象。 - 如果调用write()函数,以文本模式写入文件时还会做必要的编码。参数为
str
对象。对应下图第三行,生成字节序列(bytes)。
整个处理文本文件的过程如下图:
查看open函数默认编码方式
file1='data/test.txt'
fp=open(file1,'w')
print(fp)
fp.close()
win10下输出:
<_io.TextIOWrapper name='data/test.txt' mode='w' encoding='cp936'>
cp936即 code page 936(代码页936)是以GBK(国标扩展字符集)为基础的编码。基本和GBK差不多。
关于编码默认值的最佳建议是:别依赖默认值。如果遵从 Unicode 三明治的建议,而且始终在程序中显式指定编码,那将避免很多问题。
参考了流畅的python第四章。
python--字符/文本编码解码笔记相关推荐
- python使用base64编码解码数据
python使用base64编码解码数据 base64模块是用来作base64编码解码,常用于小型数据的传输.编码后的数据是一个字符串,其包括a-z.A-Z.0-9./.+共64个字符,即可用6个字节 ...
- 利用Huffman树进行文本编码解码的实现
--------------------------------- 功能:利用Huffman树进行文本编码解码的实现 环境:WinXP,VC6.0 输入:C:\\in.txt 输出:C:\\out.d ...
- JavaScript 文本编码解码详解笔记
JavaScript 文本的编码解码 文本编码 文本编码方法分为批量编码和流编码. 1.批量编码 所谓批量编码,指的是JavaScript引擎会同步编码整个字符串.对于非常长的字符串,可能会花较长时间 ...
- 29 Python - 字符与编码
字符与编码 01 字符串本质 Python字符串相关概念 字符串 str 字节 bytes 字节数组 bytearray 电脑字符串存储机制 字符库:A.B每个字符有一个代码点 ...
- python 字符的编码和解码
什么是编码 编码是信息从一种形式或格式转换为另一种形式的过程.例如,将字符A使用ascll编码,首先在ascll中找到字符A对应的一个数字,再将该数字转化为二进制形式,供计算机读取.而不同的编码方式中 ...
- python基础(十二):字符字节编码解码
基础(十二) 字符串概述 类型 编码架构 字符串存储 常用字符编码 ASCII latin-1 UTF-8(通用性更好) UTF-16 UTF-32 内置函数 ord() chr() str.enco ...
- python 字符的编码
参考 廖雪峰-字符串和编码 https://blog.csdn.net/weixin_41789688/article/details/116787795 Unicode编码详解(一):Unicode ...
- 使用python对url编码解码
最近在抓取一些js代码产生的动态数据,需要模拟js请求获得所需用的数据,遇到对url进行编码和解码的问题,就把遇到的问题总结一下,有总结才有进步,才能使学到的知识更加清晰.对url进行编码和解码,py ...
- 使用python对url编码解码 (转)
写cgi经常碰到的一个问题就是对url进行编码和解码,python提供了很方便的接口进行调用. url中的query带有特殊字符(不是url的保留字)时需要进行编码. 当url中带有汉字时,需要特殊的 ...
最新文章
- Ie html button消失,input 按钮在IE下兼容问题
- 【CV】基于python和OpenCV构建智能停车系统
- php 新浪url,PHP URL函数详解
- 找回Kitkat的AppOps
- 捍卫军人的尊严(武汉548公交车一幕)
- Java 异步回调机制实例解析
- 对短链接服务暴露的URL进行网络侦察
- 2018年下半年系统集成项目管理工程师真题及答案解析
- 瑞利分布与瑞利衰落信道
- h3c 出口路由器mac地址过滤
- 手把手教你用Python网络爬虫获取壁纸图片!
- Canal.deployer 启动报错说CHARACTER SET 'utf8' COLLATE 'utf8_unico', expect null,rkdown编辑器
- 两款程序员的好帮手——BitNami,Hoo WinTail
- 数据库课程设计------书店管理系统
- ipynb文件过大打开浏览器崩溃解决方法
- column ‘_id‘ does not exis报错
- 2018年天津大学夏令营机试第一题
- c语言300行代码大作业,C语言300行代码
- 【oracle】oracle创建表、创建索引、创建自增id
- Libevent之信号事件管理
热门文章
- couchbase_具有Couchbase,Java EE和WildFly的CRUD Java应用程序
- neo4j cypher_Neo4j:使用Cypher生成实时建议
- 摆脱冷气_摆脱匿名类
- Apache Camel 3.2 – Camel的无反射配置
- 只读副本和Spring Data第4部分:配置只读存储库
- 使用Spring Cloud HystrixCommands的功能Hystrix
- 提示:通过URL激活并发送参数
- junit测试方法_JUnit测试方法订购
- 为什么猫王不应该访问Java
- ANTLR和Jetbrains MPS:解析文件并以树符号显示AST