5.字符编码梳理

字符编码:
字符编码的种类和进化流程
在哪里需要字符编码的转换?
输入保存至计算机流程
解释器读写python文件流程
python默认的编码
两种python的数据类型以及对应的存入数据
小结:
python 中的unicode的正确用法
python编码中最常见的两个错误
encode和decode
unicode error实验
encode error实验
decode error实验
实践中的注意事项:

字符编码:

字符编码(英语:Character encoding)、字集码是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。

字符编码的种类和进化流程

注意:上图中的扩展ascii表和gb3212等编码方式到unicode编码方式中间的箭头,仅仅表示编码的历史进化,而不是unicode来自gbk等编码方式

常用转换关系:

gbk<=======>unicode

utf-8<=======>unicode

就是通过以上的转换,将GBK编码方式的文件,转换成UTF-8格式的

在哪里需要字符编码的转换?

了解了字符编码的种类之后,我们需要了解,在什么地方,使用什么样的编码,以及为什么要使用这些编码方式。

输入保存至计算机流程

上图表示了计算机解读和存储我们在编辑器中输入字符的过程。可能中间部分的表述并不是很准确(也可以是gbk,主要取决于编辑器的编码方式),但是能大致的说明“明文————>高低电平”的转换过程。

在这里我们需要特别注意的是文本编辑器存储到内存过程中,是不是内存中只能存在unicode方式的编码。

解释器读写python文件流程

python默认的编码

  1. python2 默认使用ascii
  2. python3 默认使用utf-8

两种python的数据类型以及对应的存入数据

数据类型:存入数据(默认编码为xxxx的二进制数)

  • python2.x:

    1.str(字符串):bytes

    2.unicode(字节串):unicode

  • python3.x:

    1.str(字符串):unicode

    2.bytes(字节串):bytes

首先解决一下“什么是字节串?”这个问题:

python2.x中str的类型存入数据为bytes(这也是为什么在出现python2的unicode错误时,在原定义的字符串前添加一个‘u’,就有可能解决问题)。bytes代表的是(二进制数的序列),通过ascii编码后才是我们看到的字符形式,如果我们单独取出一个字节,可以发现它的切片是一个数字

print(b‘12ffse‘[0])

由此也可以推出,字节类型只能允许ascii字符?

简单来说就是把人类通用的语言符号翻译成计算机通用的对象,而反向的翻译过程自然就是解码了。Python 中的字符串类型代表人类通用的语言符号,因此字符串类型有encode()方法;而字节类型代表计算机通用的对象(二进制数据),因此字节类型有decode()方法

为什么说python3规范了默认str的字符编码是unicode使编码更加规范方便了呢?

可以参考一下上方的unicode和utf8以及gbk之间的转换关系。

同时测可以测试一下以下代码:

print(type(‘hello‘+u‘world‘))

(在python2环境中运行)

相同的方式,在python3中可以这样实验:

print(‘hello‘+b‘world‘)

这个实验的目的就是:在不同的两个解释器中,拼接两个不同编码类型的字符串。

从而可以看出python2在字符编码上的“宽容”容易造成一些未知错误。而python3在字符编码方面的严格要求,决定了程序运行的规范和稳定性

更多关于字符编码理解的实验:http://python.jobbole.com/84839/

小结:

文本编辑器的编码,由文本编辑器的设置决定

语言解释器的解码方式,有语言解释器的默认设置和打开代码的抬头(python解释器默认设置第一二行能有效定义解码方式;#coding:UTF-8

如果说,语言解释器的解码方式和文本编辑器的编码不同,就会出现错误。

如果说,文本编辑器打开文件的编码和文件存储定义的解码方式不同,也会出现错误

说到错误,上面链接的作者在git上有一篇关于python中unicode正确使用方法的文章https://github.com/rainyear/pytips/blob/master/Markdowns/2016-03-17-Bytes-decode-Unicode-encode-Bytes.md ,我觉得里面例子很有意义,所以下面就是照着他的方式敲一遍实验代码用于明确python中的编码错误。

python 中的unicode的正确用法

python编码中最常见的两个错误

UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-1: ordinal not in range(128)

UnicodeDecodeError: ‘utf-8‘ codec can‘t decode bytes in position 0-1: invalid continuation byte

encode和decode

encode和decode都是翻译的过程,而ascii和unicode在本质上都像是一本将人类语言和就算计语言对应起来的字典。而且这两本本字典有厚有薄,ASCII 只包含了26个基本拉丁字母、阿拉伯数目字和英式标点符号一共128个字符,因此只需要(不占满)一个字节就可以存储,而 Unicode 则涵盖的数据除了视觉上的字形、编码方法、标准的字符编码外,还包含了字符特性,如大小写字母,共可包含 1.1M 个字符,而到现在只填充了其中的 110K 个位置。

unicode error实验

利用一个函数来展现上面的两个错误

encode error实验

def try_encode(s, encoding = ‘utf-8‘):
    try:
        print(s.encode(encoding))
    except UnicodeEncodeError as err:
        print(err)
# 定义一个测试字符串默认编码的函数,传入默认解码方式为utf-8

s = ‘4b‘
try_encode(s)
try_encode(s,‘ascii‘)
# 使用ascii的方式解码

b = ‘城‘
try_encode(b)
try_encode(b,‘ascii‘)
try_encode(b,‘GB2312‘)

反馈结果:

b‘4b‘
b‘4b‘
b‘\xe5\x9f\x8e‘
‘ascii‘ codec can‘t encode character ‘\u57ce‘ in position 0: ordinal not in range(128)
b‘\xb3\xc7‘

结果分析:

由于 UTF-8 对 ASCII 的兼容性,"4b" 可以用 ASCII 进行编码;而 "城"不能使用ascii编码,因为它已经超出了 ASCII 字符集的 128 个字符,所以引发了 UnicodeEncodeError;而 "城" GB2312 中的码位是 b‘\xd3\xea‘,与 UTF-8 不同,但是仍然可以正确编码。因此如果出现了 UnicodeEncodeError 说明你用错了字典,要翻译的字符没办法正确翻译成码位!

decode error实验

def try_decode(s, decoding = ‘utf-8‘):
    try:
        print(s.decode(decoding))
    except UnicodeDecodeError as err:
        print(err)

s = b‘4b‘
try_decode(s)
try_decode(s,‘ascii‘)

b = b‘\xb3\xc7‘
try_decode(b)
try_decode(b,‘ascii‘)
try_decode(b,‘GB2312‘)
try_decode(b,‘GBK‘)
try_decode(b,‘Big5‘)

try_decode(b.decode(‘GB2312‘).encode())
# byte - decode - unicode - encode - byte

反馈结果:

4b
4b
‘utf-8‘ codec can‘t decode byte 0xb3 in position 0: invalid start byte
‘ascii‘ codec can‘t decode byte 0xb3 in position 0: ordinal not in range(128)
城
城
傑
城

一般后续出现的字符集都是对 ASCII 兼容的,可以认为 ASCII 是他们的一个子集,因此可以用 ASCII 进行解码(编码)的,一般也可以用其它方法;对于不是不存在子集关系的编码,强行解码有可能会导致错误或乱码!

实践中的注意事项:

  1. 记清楚编码和解码的方向
  2. 在python中尽量采用utf-8,输入或者输出的时候根据需求确定是否需要编码成二进制

附件列表

时间: 2024-10-26 16:23:00

5.字符编码梳理的相关文章

字符集和字符编码

1. 概述 现在的编程语言对字符串的处理一般封装比较好,所以平时编写代码,很少要自己考虑字符编码问题.以前学习xml时,由于xml的存储涉及到编码格式,查过一些资料,知道一些概念,GB2312.Unicode.Utf-8.Utf-16.UCS-2等,但这些概念之间什么关系,仍然一知半解.最近要做国际化,需要把不支持Unicode的程序升级为Unicode,借着这个机会,把其中的知识梳理了一遍,对字符编码的理解算更系统化了,在此总结一下. 2. 字符集和字符编码 首先明确两个概念,"字符集&quo

精述字符编码(读这篇绝对不够)

带你了解ASCII,Latin1,ANSI,Unicode,UCS-2,UCS-4,UTF-8,UTF-16,UTF-32,GB2312,GB13000,GBK,GB18030,BIG5,BOM,BMP,Littile Endian,Big Endian,内码,外码,CodePage. 1.导语 字符编码(Character Encoding)是计算机显示文本的基础,是每一位IT从业者必知的计算机基础知识点,如同数值在计算中如何存储表示,那么基础,那么重要.然因字符编码历史久远,变更频繁,地域差

字符编码发展史

下文为转载内容,来源:http://www.cnblogs.com/alex3714/articles/5465198.html python解释器在加载 .py 文件中的代码时,会对内容进行编码(默认ascill) ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言,其最多只能用 8 位来表示(一个字节),即:2**8 = 256-1,所以,

凝思磐石4.2系统字符编码的修改

工作原因,用到凝思4.2的操作系统.装系统的时候,运维人员问我字符编码设置什么样的,我想UTF-8是国际编码,随口就说UTF-8吧.哪知道,单位里系统都是gb2312的.这样,其他系统上生成的文件,拷贝的本地,系统间的字符编码不一致,导致乱码.这里就简单梳理一下,字符编码的关系吧. 首先,最关键的当然是系统本身的字符编码,再往上层看,就是Shell终端的编码.只有Shell终端的编码和系统本身的编码一致的时候,我们在终端里看到的中文才不会是乱码.然后再是系统和系统之间的编码,只有两个系统之间的编

字符集与字符编码 (charset &amp; encoding)

乱码是个大坑,相信每个人都遇过,而且是个绕不过去的坑.我理解每个程序员都应该写一篇编码相关的博文,梳理自己对这一块的理解,下面是我反复理解多次之后的学习小结. 1.从记事本的不同编码说起: 打开记事本,输入“我我”,保存为ansi编码(其实是gb2312,这也是默认编码).再分别另存为unicode(其实是utf-16 little endian).unicodeBigEndian(其实是utf-16 big endian).utf8,用UltraEdit打开,切换到二进制模式,内容如下: 编码

Python中的字符串与字符编码

原文地址:点击这里 本节内容: 前言 相关概念 Python中的默认编码 Python2与Python3中对字符串的支持 字符编码转换 一.前言 Python中的字符编码是个老生常谈的话题,同行们都写过很多这方面的文章.有的人云亦云,也有的写得很深入.近日看到某知名培训机构的教学视频中再次谈及此问题,讲解的还是不尽人意,所以才想写这篇文字.一方面,梳理一下相关知识,另一方面,希望给其他人些许帮助. Python2的 默认编码 是ASCII,不能识别中文字符,需要显式指定字符编码:Python3的

到底什么是字符编码

我之前老是有这种感觉, 就是明明已经看过很多关于字符编码的资料了, 感觉字符编码相关的知识点不难理解, 觉得自己已经把字符编码给弄懂了, 但当别人问我到底什么是字符编码, Unicode是什么啊, UTF-8又是什么的时候, 我又结结巴巴的说不清楚, 或者只能给个含糊不清的回答, 老是把相关的知识点给弄混. 所以这篇博客, 就是要把字符编码给真正的搞懂, 把相关的知识点梳理清楚. 到底什么是字! 符! 编! 码?!!! 我们所理解的"字符编码(名词)"包含两个部分: 1.字符集 2.编

python字符编码

1. 字符编码简介 阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符 ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符) 后来为了将拉丁文也编码进了ASCII表,将最高位也占用了 阶段二:为了满足中文,中国人定制了GBK GBK:2Bytes代表一个字符 为了满

刨根究底字符编码之十二——UTF-8究竟是怎么编码的

UTF-8究竟是怎么编码的 1. UTF-8编码是Unicode字符集的一种编码方式(CEF),其特点是使用变长字节数(即变长码元序列.变宽码元序列)来编码.一般是1到4个字节,当然,也可以更长. 为什么要变长呢?这可以理解为按需分配,比如一个字节足以容纳所有的ASCII码字符,那何必补一堆0用更多的字节来存储呢? 实际上变长编码有其优势也有其劣势,优势是节省空间.自动纠错性能好.利于传输.扩展性强,劣势是不利于程序内部处理,比如正则表达式检索:而UTF-32这样等长码元序列(即等宽码元序列)的