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第四章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/333743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

neo4j cypher_Neo4j:Cypher – Neo.ClientError.Statement.TypeError:不知道如何添加Double和String...

neo4j cypher最近&#xff0c;我将支持Neo4j的应用程序从Neo4j 3.2升级到Neo4j 3.3&#xff0c;发现围绕类型强制的行为发生了有趣的变化&#xff0c;导致我的应用程序抛出了很多错误。 在Neo4j 3.2和更早版本中&#xff0c;如果将String添加到Double&#xff0c;它将把Double…

easyui数据表格显示复选框_【Excel技巧】使用控件一键切换实现单位元和万元随意显示...

工欲善其事&#xff0c;必先利其器。职场上亦是如此。Excel报表想要做得完美&#xff0c;首先肯定Excel要精通。做一份Excel报表&#xff0c;如果涉及到金额&#xff0c;当金额比较大&#xff0c;单位到底是用元还是万元&#xff0c;经常是大家纠结的一个问题。我们今天就来介绍…

正则表达式的固化分组

固化分组&#xff0c;又叫原子组。 语法格式&#xff1a;(?>…) 我们在使用非贪婪模式时&#xff0c;匹配过程中可能会进行多次的回溯&#xff0c;回溯越多&#xff0c;正则表达式的运行效率就越低。而固化分组就是用来减少回溯次数的。 实际上&#xff0c;固化分组 (?…

Requests库基本使用

requests库基本使用基本流程python中一个基于网络请求的模块&#xff0c;功能强大&#xff0c;简单便捷&#xff0c;效率极高&#xff0c;可以取代古老的urllib模块。作用&#xff1a;模拟浏览器向服务器发起请求。基本流程 1.指定URL2.对指定的URL发起请求(get或post)3.获取响…

tls 使用java生成_同时使用传入和传出连接时,相互TLS身份验证存在Java问题

tls 使用java生成在大多数企业环境中&#xff0c;应用程序之间的连接中使用某种形式的安全通信&#xff08;例如TLS或SSL&#xff09;。 在某些环境中&#xff0c; 相互&#xff08;双向&#xff09;身份验证也是一项非功能性要求。 有时将其称为双向SSL或双向TLS身份验证。 因…

正则表达式的环视实际应用案例

一、千位分隔符案例&#xff08;一&#xff09; 逆序环视和顺序环视结合应用。 **需求&#xff1a;**数字格式化成用 , 分隔的货币格式。 正则表达式&#xff1a;(?n)(?<\d)(?<!\.\d*)(?(\d{3})(\.|$)) 测试代码&#xff1a; double[] data new double[] { 0,…

软件工程专插本_2021年专插本部分招生专业(拟),广科/广东理工/华商/培正/松田/工商大!...

小师姐从各专插本交流群中收集到了6所院校的2021年本科插班生拟招生专业&#xff1a;广东理工学院、广东科技学院、广东财经大学华商学院、广州大学松田学院、广东培正学院、广东工商职业技术大学。ps&#xff1a;以下只是拟招生专业&#xff0c;具体还是以考试院公布的为准。另…

Requests库实战(一)---网页采集器

网页采集器User-Agent伪装完整代码功能&#xff1a;通过动态url来实现用户输入搜索关键字&#xff0c;返回搜索到的页面。User-Agent伪装 一种反爬机制。 原理&#xff1a;网站的服务器会检测对于请求的载体身份标识&#xff0c;如果检测到请求的载体身份标识为某一款浏览器&a…

ES6 对正则表达式的扩展

文章目录修饰符 y修饰符 uECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在 2015 年 6 月正式发布了。它的目标&#xff0c;是使得 JavaScript 语言可以用来编写复杂的大型应用程序&#xff0c;成为企业级开发语言。修饰符…

transformer机制讲解_【核心代码解读】Transformer-XL

[论文] Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context​arxiv.orgMotivationTransformer在预训练阶段&#xff0c;设置了固定序列长度max_len的上下文&#xff0c;finetuning阶段&#xff0c;模型不能获取大于max_len的上下文依赖&#xff1b;Tran…

Neo4j导入:java.lang.IllegalStateException:不支持在单个导入中混合指定和未指定的组所有物...

休息片刻之后&#xff0c;我最近一直在使用Neo4j导入工具 &#xff0c;并遇到了我最初不理解的有趣的错误消息。 我有一些CSV文件&#xff0c;其中包含要导入Neo4j的节点。 它们的内容如下所示&#xff1a; $ cat people_header.csv name:ID(Person)$ cat people.csv "…

Requests库实战(二)---破解百度翻译

功能&#xff1a;爬取到页面中翻译后的文本数据 获取请求地址和请求方式 先输入dog翻译一下&#xff0c;发现是Ajax请求(动态实时刷新页面)&#xff0c;Ajax请求的数据包可以在网络的XHR中看到。找到输入dog的数据包&#xff0c;通过标头的表单数据kw:dog以及响应的结果就可以…

局部变量的赋值问题

int i 5; i 10;变量 i 在栈帧里面的局部变量表里面&#xff0c;这个局部变量表类似一个数组&#xff0c;里面包含了一些“槽位”来存放局部变量&#xff0c;i 这个变量&#xff0c;就是在局部变量表中的某一个槽位里面&#xff0c;并且 i 只会占用一个槽位&#xff0c;对变量…

php生成 sku_高并发下,php与redis实现的抢购、秒杀功能

抢购、秒杀是如今很常见的一个应用场景&#xff0c;主要需要解决的问题有两个&#xff1a;1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少&#xff08;"超卖"问题&#xff09;对于第一个问题&#xff0c;已经很容易想到用缓存来处理抢购&#xff0c;…

lambda :: -_无需再忙了:Lambda-S3缩略图,由SLAppForge Sigma钉牢!

lambda :: ->如果你还没有注意到了&#xff0c;我最近被唠叨试图开始使用时&#xff0c;我遭遇了陷阱AWSλ-S3正式例子 。 虽然大多数这些愚蠢的错误的指责是对我自己的懒惰&#xff0c;过度自尊和缺乏对细节的关注&#xff0c;我个人觉得&#xff0c;在开始与一家领先的无服…

Requests库实战(三)---爬取豆瓣电影详细信息

完整代码 爬取豆瓣电影的详细信息 地址&#xff1a;豆瓣电影动画 向下滑动时新增的数据也是Ajax请求&#xff0c;原理和上一个项目是一样的。唯一的不同是此处请求url携带了多个参数 import requests import json header{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x6…

lineseparator_首选System.lineSeparator()以用Java编写系统相关的行分隔符字符串

lineseparatorJDK 7在java.lang.System类上引入了一个名为lineSeparator&#xff08;&#xff09;的新方法。 该方法不期待任何参数&#xff0c;并返回一个String &#xff0c;它表示“取决于系统的行分隔符字符串。” 此方法的Javadoc文档还指出System.lineSeparator() “始终…

JavaScript(JS)中与正则表达式有关的方法介绍

文章目录RegExpRegExp 对象的属性compiletestexecString一共有 7 个与正则表达式式相关的方法&#xff0c;这些方法分别来自于 RegExp 与 String 对象。RegExp RegExp 对象表示正则表达式, 主要用于对字符串执行模式匹配. 语法: new RegExp(pattern[, flags]) 参数 pattern …

Requests库实战(四)---爬取肯德基餐厅地址信息

功能&#xff1a;爬取查询后的肯德基餐厅的地址信息 地址&#xff1a;http://www.kfc.com.cn/kfccda/storelist/index.aspx 亮点是post请求的参数有两组&#xff1a;查询字符串参数&#xff0c;表单数据。 对于post请求,由于url中隐藏了许多参数&#xff0c;所以引入了表单数据…

显示请求_学习记录:HTTP的响应与请求amp;Curl

本文包含四个部分&#xff0c;简要介绍HTTP请求、HTTP响应、chrome开发者查看、与CURL命令。Part1&#xff1a;HTTP请求1GET请求指定的页面信息&#xff0c;并返回实体主体。2HEAD类似于get请求&#xff0c;只不过返回的响应中没有具体的内容&#xff0c;用于获取报头。3POST向…