python 语法基础之字符集编码

Python初学者编码实践中经常遇到encode error,decode error,如下:

例1:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u5728' in position 1

例2:

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

1、百度的时候,大家都建议在代码文件头加上字符集定义:

# -*- coding: utf-8 -*-

这种方法大部分情况下可以解决大部分的问题。那么它解决的是什么问题呢?

我们需要理解两个概念:

1)、# -*- coding: utf-8 -*- 的作用是声明 python源代码文件的编码格式。 谁会读取Python的源代码呢? 一个是IDE编辑工具,比如pycharm,nodpad++,editpluss等,我们在写代码的时候使用。

2)、另一个是Python解释器,是执行Python程序的时候使用。

当我们使用IDE编辑器打开Python代码的时候,如果出现乱码,我们都知道是编辑器的解码方式和代码文件的编码方式不一致导致的。需要修改编辑器的解码方式。

那么Python解释执行Python程序的时候使用的是设么解码方式呢?可以用下面的方式查看:

sys.getdefaultencoding()

可以用下面的方式修改:

reload(sys)
sys.setdefaultencoding('utf-8')
sys.getdefaultencoding()

所以,代码文件第一行加 字符集定义,解决Python解释器读取Python代码文件时的字符集识别问题

2、在print的时候出现异常,或者写文件,或者解析网络报文,或者做str对象处理的时候出现乱码。

这个时候我们需要理解:

1)、文件读写、网络报文读写都可以理解为IO读写。是byte处理,所以读写前后需要使用同样的字符编码方式。

2)、print、str对象的处理涉及到终端的编码格式。print之后,在pycharm的输出窗口,或者windows的CMD命令行窗口,或者Linux的shell窗口,需要适配终端的编码方式

3)、字符编码基本可分为三大类:起源于美国的ASCII,支持英文字符、数字、标点符号、键盘上的特殊字符;国际编码unicode,支持ascII的字符集外,又支持中文,韩语,日语等。因为unicode占用空间大,所以又出现了utf-8。需要强调的一点是

unicode:简单粗暴,所有字符都是2Bytes,优点是字符->数字的转换速度快,缺点是占用空间大

utf-8:精准,对不同的字符用不同的长度表示,优点是节省空间,缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示

1.内存中使用的编码是unicode,用空间换时间(程序都需要加载到内存才能运行,因而内存应该是尽可能的保证快)

2.硬盘中或者网络传输用utf-8,网络I/O延迟或磁盘I/O延迟要远大与utf-8的转换延迟,而且I/O应该是尽可能地节省带宽,保证数据传输的稳定性。

下面详细介绍了unicode和utf-8的使用场景:

在程序执行之前,内存中确实都是unicode编码的二进制,比如从文件中读取了一行x="egon",其中的x,等号,引号,地位都一样,都是普通字符而已,都是以unicode编码的二进制形式存放与内存中的

但是程序在执行过程中,会申请内存(与程序代码所存在的内存是俩个空间),可以存放任意编码格式的数据,比如x="egon",会被python解释器识别为字符串,会申请内存空间来存放"egon",然后让x指向该内存地址,此时新申请的该内存地址保存也是unicode编码的egon,如果代码换成x="egon".encode('utf-8'),那么新申请的内存空间里存放的就是utf-8编码的字符串egon了

针对python3如下图

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器

如果服务端encode的编码格式是utf-8, 客户端内存中收到的也是utf-8编码的二进制。

从上面的说明,我们知道了unicode和utf-8的应用场景,就需要用下面的方式进行转换:

字符串通过编码转换为字节码,字节码通过解码转换为字符串

str--->(encode)--->bytes,bytes--->(decode)--->str

参考:

https://www.cnblogs.com/zihe/p/6993891.html

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏magicsoar

C++内存布局(1)-让new出的两个变量在堆上的地址连续

大家都知道栈的地址按照从高到低的顺序增长的, 而堆的地址是按照从底到高的顺序增长的。 int *n1 = new int(1); int *n2 = new i...

24190
来自专栏开源优测

[接口测试_B] 14 pytest+requests实战-参数化

上一篇在一个py文件中,写了一堆test_开头的方法,所有数据和用例都在一个py文件中,本篇尝试读取json文件的测试数据,执行用例。

21440
来自专栏coding for love

JS入门难点解析4-执行上下文栈

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

12440
来自专栏JMCui

MongoDB系列二(介绍).

一、特点     学习一个东西,至少首先得知道它能做什么?适合做什么?有什么优缺点吧?     传统关系型数据库,遵循三大范式。即原子性、唯一性、每列与主键直接...

30580
来自专栏用户2442861的专栏

C语言中volatile关键字的作用

由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺...

19630
来自专栏菩提树下的杨过

java 中的异步回调

异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: ? 先定义了一个CallBackTask,做为外层的面子工...

42870
来自专栏Laoqi's Linux运维专列

for 循环,while循环,break,continue,exit

39880
来自专栏武军超python专栏

2018年7月23日数据存储到文件中的代码介绍:

******************************************************************

12050
来自专栏Python

nginx配置 location及rewrite规则详解

23020
来自专栏我是攻城师

Java进阶之内存模型介绍

不管在什么编程语言里面,读取和写入都是我们程序最普遍的操作,在单线程的程序里面我们可能不关注线程的读写问题,但是一旦到多线程的环境下,读和写就会变得非常敏感。J...

8330

扫码关注云+社区

领取腾讯云代金券