热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python常见字符编码间的转换

学习Python,字符编码间的转换是绕不过去的一只拦路虎,不把编码彻底搞明白,总有一天它会猝不及防坑你一把。Python2.x和Python3.x在字符编码的设置上也有很大区别(P

  学习Python,字符编码间的转换是绕不过去的一只拦路虎,不把编码彻底搞明白,总有一天它会猝不及防坑你一把。

  Python2.x和Python3.x在字符编码的设置上也有很大区别(Python3未来将是主流,所以Python3为主),今天我们就来一起学习下。

  上一篇文章里我已经简述了Python的常见编码了,这里就不再赘述了,还不清楚的小伙伴可以先去看下:               http://www.cnblogs.com/schut/p/8406897.html

一、Unicode 和 UTF-8的纠葛  

  Unicode 起到了2个作用:


  1. 直接支持全球所有语言,每个国家都可以不用再使用自己之前的旧编码了,用unicode就可以了。(就跟英语是全球统一语言一样)

  2. unicode包含了跟全球所有国家编码的映射关系。

    Unicode解决了字符和二进制的对应关系,但是使用unicode表示一个字符,太浪费空间。例如:利用unicode表   示“Python”需要12个字节才能表示,比原来ASCII表示增加了1倍。由于计算机的内存比较大,并且字符串在内容中表示时也不会特别大,所以内容可以使用unicode来处理,但是存储和网络传输时一般数据都会非常多,那么增加1倍将是无法容忍的!!!

  为了解决存储和网络传输的问题,出现了Unicode Transformation Format,学术名UTF,即:对unicode中的进行转换,以便于在存储和网络传输时可以节省空间!

  UTF-8: 使用1、2、3、4个字节表示所有字符;优先使用1个字符、无法满足则使增加一个字节,最多4个字节。英文占1个字节、欧洲语系占2个、东亚占3个,其它及特殊字符占4个。

  UTF-16: 使用2、4个字节表示所有字符;优先使用2个字节,否则使用4个字节表示。

  UTF-32: 使用4个字节表示所有字符。

  总结:UTF 是为unicode编码 设计 的一种 在存储 和传输时节省空间的编码方案。

二、字符在硬盘上的存储

  首先要明确的一点就是,无论以什么编码在内存里显示字符,存到硬盘上都是2进制。理解这一点很重要。

  比如:    

    ascii编码(美国):
     l 0b1101100
     o 0b1101111
    v 0b1110110
     e 0b1100101
    GBK编码(中国):
     老 0b11000000 0b11001111
     男 0b11000100 0b11010000
     孩 0b10111010 0b10100010
  还要注意的一点是,
要注意的是,存到硬盘上时是以何种编码存的,再从硬盘上读出来时,
就必须以何种编码读(开头声明或转换),要不然就乱了。
三、编码的转换
  
虽然有了unicode and utf-8 ,但是由于历史问题,各个国家依然在大量使用自己的编码,
比如中国的windows,默认编码依然是gbk,而不是utf-8。
  基于此,如果中国的软件出口到美国,在美国人的电脑上就会显示乱码,因为他们没有gbk编码。
  所以该怎么办呢?
  还记得我们讲unicode其中一个功能是其包含了跟全球所有国家编码的映射关系,这时就派上用场了。
无论你以什么编码存储的数据,只要你的软件在把数据从硬盘读到内存里,转成unicode来显示,就可以了。
由于所有的系统、编程语言都默认支持unicode,那你的gbk软件放到美国电脑上,加载到内存里,变成了unicode,
中文就可以正常展示啦。
 
 Python3执行过程


  1. 解释器找到代码文件,把代码字符串按文件头定义的编码加载到内存,转成unicode

  2. 把代码字符串按照语法规则进行解释

  3. 所有的变量字符都会以unicode编码声明

  在py3上 把你的代码以utf-8编写, 保存,然后在windows上执行。
  发现可以正常执行!
  其实utf-8编码之所以能在windows gbk的终端下显示正常,是因为到了内存里python解释器把utf-8转成了unicode ,
但是这只是python3, 并不是所有的编程语言在内存里默认编码都是unicode,比如 万恶的python2 就不是,
是ASCII,想写中文,就必须声明文件头的coding为gbk or utf-8, 声明之后,python2解释器
仅以文件头声明的编码去解释你的代码,加载到内存后,并不会主动帮你转为unicode,也就是说,你的文件编码是utf-8,
加载到内存里,你的变量字符串就也是utf-8, 这意味着什么?意味着,你以utf-8编码的文件,
在windows是乱码。
其实乱是正常的,不乱才不正常,因为只有2种情况 ,你的windows上显示才不会乱。Python2并不会自动的把文件编码转为unicode存在内存里,


  1. 字符串以GBK格式显示

  2. 字符串是unicode编码

所以我们只有手动转,Python3 自动把文件编码转为unicode必定是调用了什么方法,这个方法就是,decode(解码) 和encode(编码)。
方法如下:
  
UTF-8 --> decode 解码 --> Unicode
  Unicode --> encode 编码 --> GBK / UTF-8
  例如:
  

#!/usr/bin/env python3
#
-*- coding:utf-8 -*-
#
write by congcong

s
= 匆匆
print(s)
s1
= s.decode("utf-8") # utf-8 转成 Unicode,decode(解码)需要注明当前编码格式
print(s1,type(s1))
s2
= s1.encode("gbk") # unicode 转成 gbk,encode(编码)需要注明生成的编码格式
print(s2,type(s2))
s3
= s1.encode("utf-8") # unicode 转成 utf-8,encode(编码)注明生成的编码格式
print(s3,type(s3))

规则如下:

技术分享图片

 

四、如何验证编码转对了呢?
  1、查看数据类型,python 2 里有专门的unicode 类型

   2、查看unicode编码映射表

  unicode字符是有专门的unicode类型来判断的,但是utf-8,gbk编码的字符都是str,
你如果分辨出来的当前的字符串数据是何种编码的呢? 有人说可以通过字节长度判断,
因为utf-8一个中文占3字节,gbk一个占2字节。
  看输出的字节个数,也能大体判断是什么类型。精确的验证一个字符的编码呢,就是拿这些16进制的数跟编码表里去匹配。
详细过程可以看这里:https://www.luffycity.com/python-book/di-3-zhang-python-ji-chu-2014-wen-jian-cao-4f5c26-han-shu/33-zi-fu-bian-ma-zhuan-huan.html


五、Python bytes类型
  把8个二进制一组称为一个byte,用16进制来表示。为的就是让人们看起来更可读。我们称之为bytes类型,即字节类型。

  python2的字符串其实更应该称为字节串。 通过存储方式就能看出来, 但python2里还有一个类型是bytes呀,难道又叫bytes又叫字符串?
嗯 ,是的,在python2里,bytes == str , 其实就是一回事。
  除此之外呢, python2里还有个单独的类型是unicode , 把字符串解码后,就会变成unicode。

>>> s
\xe8\xb7\xaf\xe9\xa3\x9e #utf-8
>>> s.decode(utf-8)
u
\u8def\u98de #unicode 在unicode编码表里对应的位置
>>> print(s.decode(utf-8))
路飞
#unicode 格式的字符

  Python2的默认编码是ASCII码,当后来大家对支持汉字、日文、法语等语言的呼声越来越高时,Python于是准备引入unicode,但若直接把
默认编码改成unicode的话是不现实的, 因为很多软件就是基于之前的默认编码ASCII开发的,编码一换,那些软件的编码就都乱了。所以Python 2
就直接 搞了一个新的字符类型,就叫unicode类型,比如你想让你的中文在全球所有电脑上正常显示,在内存里就得把字符串存成unicode类型。

>>> s = "路飞"
>>> s
\xe8\xb7\xaf\xe9\xa3\x9e
>>> s2 = s.decode("utf-8")
>>> s2
u
\u8def\u98de
>>> type(s2)
unicode>

  Python3 除了把字符串的编码改成了unicode, 还把str 和bytes 做了明确区分, str 就是unicode格式的字符, bytes就是单纯二进制啦。

  在py3里看字符,必须得是unicode编码,其它编码一律按bytes格式展示。

  Python只要出现各种编码问题,无非是哪里的编码设置出错了
常见编码错误的原因有以下这些: 


  • Python解释器的默认编码

  • Python源文件文件编码

  • Terminal使用的编码

  • 操作系统的语言设置

最后总结一下:
  python3  文件默认编码是utf-8 , 字符串编码是 unicode
        以utf-8 或者 gbk等编码的代码,加载到内存,会自动转为unicode正常显示。
  python2  文件默认编码是ascii , 字符串编码也是 ascii , 如果文件头声明了是gbk,那字符串编码就是gbk。
      
 以utf-8 或者 gbk等编码的代码,加载到内存,并不会转为unicode,编码仍然是utf-8或者gbk等编码。


以上内容搬运和修改自:https://www.luffycity.com/python-book/di-3-zhang-python-ji-chu-2014-wen-jian-cao-4f5c26-han-shu/33-zi-fu-bian-ma-zhuan-huan.html

  


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • PHPMailer邮件类邮件发送功能的使用教学及注意事项
    本文介绍了使用国外开源码PHPMailer邮件类实现邮件发送功能的简单教学,同时提供了一些注意事项。文章涵盖了字符集设置、发送HTML格式邮件、群发邮件以及避免类的重定义等方面的内容。此外,还提供了一些与PHP相关的资源和服务,如传奇手游游戏源码下载、vscode字体调整、数据恢复、Ubuntu实验环境搭建、北京爬虫市场、进阶PHP和SEO人员需注意的内容。 ... [详细]
author-avatar
那0年_277
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有