python2和python3编码问题
欢迎加入python学习交流群 667279387
近期有同学在群里面问编解码的问题,为啥在python2中可以到了python3中为啥不行了。其实这设计到python2和python3编码的问题。这是一篇写比较不错的文档分享:Pragmatic Unicode ,这里在原文的基础上面进行了一下整理。
一、什么是编解码
1、什么是unicode
Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
2、编码方式
字符集:为每一个字符分配一个唯一的 ID(码位 / 码点 / Code Point),编码规则:将码位转换为字节序列的规则(编码/解码 可以理解为 加密/解密 的过程)。为了将unicode字符转成bytes,需要进行编码,常见的编码方案有:UTF-16, UTF-32, UCS-2, UCS-4, UTF-8
二、python中的编解码
1、python2
1、str: 是比特序列
2、unicode: code points序列
>>> my_string = "Hello World"
>>> type(my_string)
<type 'str'>
>>> my_unicode = u"Hi \u2119\u01b4\u2602\u210c\xf8\u1f24"
>>> type(my_unicode)
<type 'unicode'>
(1).encode() 和 .decode()
unicode .encode() → bytes //encode函数就是将unicode转换成bytes
bytes .decode() → unicode //对应的解码过程就是将bytes转成unicode
>>> my_unicode = u"Hi \u2119\u01b4\u2602\u210c\xf8\u1f24"
>>> len(my_unicode)
9
>>> my_utf8 = my_unicode.encode('utf-8')
>>> len(my_utf8)
19
>>> my_utf8
'Hi \xe2\x84\x99\xc6\xb4\xe2\x98\x82\xe2\x84\x8c\xc3\xb8\xe1\xbc\xa4'
>>> my_utf8.decode('utf-8')
u'Hi \u2119\u01b4\u2602\u210c\xf8\u1f24'
更多请参考官方教程:https://docs.python.org/2/library/stdtypes.html?highlight=decode#str.decode
(2)编解码错误和处理
许多编码方案并能将全部的unicode字符进行编码。
>>> my_unicode.encode('ascii')
Traceback (most recent call last):
UnicodeEncodeError: 'ascii' codec can't encode characters in
position 3-8: ordinal not in range(128)
同样反过来,也并不是每一个str都是合法的unicode编码。
>>> my_utf8.decode("ascii")
Traceback (most recent call last):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in
position 3: ordinal not in range(128)
>>> "\x78\x9a\xbc\xde\xf0".decode("utf-8")
Traceback (most recent call last):
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x9a in
position 1: invalid start byte
这是官网给出来的一个在不能完全编码采用哪种方案进行处理的示例。
>>> unicode('\x80abc', errors='strict')
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
(3)令人抓狂的隐式转换
下面就是python2中比较用起来爽,但是有时又让你很抓狂的东西—隐式转换。看下面这个例子:
>>> u"Hello " + "world"
u'Hello world'
>>> u"Hello " + ("world".decode("ascii"))
u'Hello world'
>>> sys.getdefaultencoding()
'ascii'
你可以将str和unicode进行拼接,语法解析器会自动给你做隐式转换。当然在很多时候是可以很好完成你的工作的,但是有时却不好使:
>>> u"Hello " + my_utf8
Traceback (most recent call last):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in
position 3: ordinal not in range(128)
>>> u"Hello " + (my_utf8.decode("ascii"))
Traceback (most recent call last):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in
position 3: ordinal not in range(128)
2、python3
这里将python2和python3做了一个对比放在下面的表格里面了。
| —— | python2 | python3 |
|---|---|---|
| str | a sequence of bytes | a sequence of code points (unicode) |
| unicode | a sequence of code points (unicode) | —— |
| bytes | —— | a sequence of bytes |
也就是说在python中,字符串为unicode格式的码位。下面看看在python3中的示例
>>> my_string = "Hi \u2119\u01b4\u2602\u210c\xf8\u1f24"
>>> type(my_string)
<class 'str'>
>>> my_bytes = b"Hello World"
>>> type(my_bytes)
<class 'bytes'>
(1)encode和decode
在python3中,字符串str是unicode的,你可以利用encode函数将其转成其他的编码格式。
>>> nonlat = '字' //unicode格式
>>> nonlat
'字'
>>> print(nonlat)
字
>>> bytes(nonlat)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: string argument without an encoding
>>> bytes(nonlat, 'utf-8')//和下面直接调用encode方法的区别可以参考下面给出的Stack Overflow的链接
b'\xe5\xad\x97'
>>> nonlat.encode() //encode函数默认使用utf-8编码
b'\xe5\xad\x97'
>>> nonlat.encode('utf-16')
b'\xff\xfeW['
>>> b'\xff\xfeW['.decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
>>> b'\xff\xfeW['.decode('utf-16')
'字'
区别:https://stackoverflow.com/questions/14472650/python-3-encode-decode-vs-bytes-str
更多请参考官方文档:https://docs.python.org/3/library/stdtypes.html?highlight=decode#bytes.decode
(2)无隐式转换
在python3中没有了python2中的隐式转换。你必须两种格式分开来处理。
>>> "Hello " + b"world"
Traceback (most recent call last):
TypeError: Can't convert 'bytes' object to str implicitly
>>> "Hello" == b"Hello"
False
>>> d = {"Hello": "world"}
>>> d[b"Hello"]
Traceback (most recent call last):
KeyError: b'Hello'
例如读取文件的时候,你就必须要注意格式的问题:
>>> open("hello.txt", "r").read()
'Hello, world!\n'
>>> open("hello.txt", "rb").read()
b'Hello, world!\n'
>>> open("hi_utf8.txt", "r").read()
'Hi \xe2\u201e\u2122\xc6\xb4\xe2\u02dc\u201a\xe2\u201e\u0152\xc3\xb8\xe1\xbc\xa4'
>>> open("hi_utf8.txt", "r",
... encoding=locale.getpreferredencoding()).read()
'Hi \xe2\u201e\u2122\xc6\xb4\xe2\u02dc\u201a\xe2\u201e\u0152\xc3\xb8\xe1\xbc\xa4'
>>> open("hi_utf8.txt", "r", encoding="utf-8").read()
'Hi \u2119\u01b4\u2602\u210c\xf8\u1f24'
>>> open("hi_utf8.txt", "rb").read()
b'Hi \xe2\x84\x99\xc6\xb4\xe2\x98\x82\xe2\x84\x8c\xc3\xb8\xe1\xbc\xa4
(3)编程注意点
1、Unicode sandwich
Bytes on the outside, unicode on the inside Encode/decode at the edges
2、Know what you have
Bytes or Unicode? If bytes, what encoding?
>>> print type(my_unicode)
<type 'unicode'>
>>> print repr(my_unicode)
u'Hi \u2119\u01b4\u2602\u210c\xf8\u1f24'
参考资料:
1、https://en.wikipedia.org/wiki/Unicode
2、https://docs.python.org/2/howto/unicode.html
3、https://stackoverflow.com/questions/14472650/python-3-encode-decode-vs-bytes-str
4、https://docs.python.org/3/library/stdtypes.html?highlight=decode#bytes.decode
欢迎加入python学习交流群 667279387
python2和python3编码问题的更多相关文章
- 字符编码、python2和python3编码的区别
目录 字符编码 文本编辑器存储信息的过程 python解释器解释python代码的流程 python解释器与文本编辑器的异同 不同编码格式存入与读取数据的过程 乱码的分析 python2和python ...
- python2和python3编码
python2编码 unicode:unicode 你好 u'\u4f60\u597d' | | | | encode('utf8')| |decode('utf8') encode('gbk')| ...
- Python2 和 Python3 编码问题
基本存储单元 位(bit, b):二进制数中的一个数位,可以是0或者1,是计算机中数据的最小单位. 字节(Byte,B):计算机中数据的基本单位,每8位组成一个字节. 1B = 8b 各种信息在计算机 ...
- python2与python3编码
#coding:utf8#一#1.在python2中,默认以ASCII编码chcp 936import sysprint sys.getdefaultencoding()# ascii#str:byt ...
- Python2和Python3编码的区别
Python2 python2中有两种储存变量的形式,第一种:Unicode:第二种:按照coding头来的. 假设python2用utf8存储x='中文',当你print(x)的时候,终端接收gbk ...
- python2与python3编码问题
python2: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 33: 解决办法: 在报错的页面添加代码: ...
- python2与python3编码(练习)
#_author:来童星#date:2019/12/9import jsons='star'a=s.encode('utf8')print(s,type(s))# star <class 'st ...
- pickle 在python2 to python3 编码出现错误
pickle.load(file) UnicodeDecodeError: 'ascii' codec can't decode byte 0xf5 in position 2: ordinal no ...
- Python全栈之路----Python2与Python3
金角大王Alex python 之路,致那些年,我们依然没搞明白的编码 python2与python3的区别 py2 str = bytes 为什么有bytes? 是因为要表示图片.视频等二进制格式 ...
随机推荐
- 猫眼电影App抓包获取评论数据接口
之前在CSDN程序人生公众号上看到了这篇文章<邪不压正>评分持续走低,上万条网友评论揭秘,是救救姜文还是救救观众?,文中提到了通过抓包猫眼App发现了评论的数据接口:http://m.m ...
- 查看redis占用内存大小的方法
查看redis占用内存大小的方法 <pre>redis-cli auth 密码info</pre><pre># Memory used_memory:1349009 ...
- 可保图片不变形的object-fit
Object-fit 我们有时候浏览一些网站的时候,偶尔会遇到这种情况: 明显它喵的形变了,尤其是这种这么业余的失误,还是出现在一个专门做图片的网站上. 产生这种现象的原因是:图片写了固定的宽高,这 ...
- C语言:大数取余
大数取余数(数组) 今天做学校的oj时遇到一题,问题可见一下截图: 查遍各大论坛,都没有遇到合适的方法,普通方法不可用,要采用数组的形式. 被除数超过long long类型,不能采用常规思路,否则会出 ...
- ATM功能实现项目
一.模拟实现一个ATM + 购物商城程序 1.额度 15000或自定义2.实现购物商城,买东西加入 购物车,调用信用卡接口结账3.可以提现,手续费5%4.支持多账户登录5.支持账户间转账6.记录每月日 ...
- 【持续更新】【pat】pat刷题技巧记录
修改code completion快捷键位CTRL+ENTER,帮助提示函数名称 修改命令行提示符的属性,开启快速编辑模式,方便调试 添加c++11语言标准支持 开启代码调试功能 对输入的字符串进行切 ...
- 05-商品类别数据和VUE展示
一.商品类别数据和VUE展示 1.商品类别数据接口 将商品类别数据展示出来,视图(views.py)代码如下: class CategoryViewset(mixins.ListModelMixin, ...
- nyoj 263-精 挑 细 选 (sort(P, P+m, cmp); bool cmp(node a, node b)...)
263-精 挑 细 选 内存限制:64MB 时间限制:3000ms 特判: No 通过数:14 提交数:26 难度:1 题目描述: 小王是公司的仓库管理员,一天,他接到了这样一个任务:从仓库中找出一根 ...
- django_1:配置文件
工程下: settings.py(建议设置成如下) DATABASES #数据库配置 DEBUG = True ...
- ubunit 16 安装pip
pip是一个用来安装和管理python包的工具.已经内置到python2.7.9和python3.4及其以上的版本里. python2.7执行: sudo apt-get install python ...