更多课程 选择中心


Python培训

400-111-8989

Python2 和 Python3 中的默认编码差异


最近在使用 Python3.4 做一些脚本实现,发现对于编码的处理上和 Python2.6 有很大的不同,就此机会把相关知识做个梳理,方便需要的时候查阅。

先说下概念和差异:

脚本字符编码:就是解释器解释脚本文件时使用的编码格式,可以通过 # -\*- coding: utf-8 -\*- 显式指定

解释器字符编码:解释器内部逻辑过程中对 str 类型进行处理时使用的编码格式

Python2 中默认把脚步文件使用 ASCII 来处理(历史原因请 Google)

Python2 中字符串除了 str 还有 Unicode,可以用 decode 和 encode 相互转换

Python3 中默认把脚步文件使用 UTF-8 来处理(终于默认就支持中文了,赞)

Python3 中文本字符和二进制分别使用 str 和 bytes 进行区分,也是使用 decode 和 encode 进行相互转换

关于默认脚本字符编码,因为对脚步文件处理的默认编码格式变了,所以很多针对内容的处理,都发生了变化,比如下面这个脚本。

import sys

print(sys.getdefaultencoding())

print('中文')

使用 Python3.4 解释器运行结果如下:

> python34 test.py

utf-8中文

使用 Python2.6 解释器运行结果如下:

> python26 test.py

File "test.py", line 4SyntaxError: Non-ASCII character '\xe4' in file test.py on line 4, but no encoding declared; see #/peps/pep-0263.html for details

使用 Python2.6 报错就是因为第一条说的「Python2 中默认把脚步文件使用 ASCII 来处理」,但是脚步文件包含了中文,ascii 又没有覆盖中文,所以报错。如果我们把脚步稍作修改:

# -*- coding: utf-8 -*-import sys

print(sys.getdefaultencoding())

print('中文')

增加了脚本字符编码的说明,再次使用 Python2.6 解释器运行结果为:

> python26 test.py

ascii

涓枃

因为明确指定了脚步文件编码格式为 utf-8,所以读取没问题,也就是说如果 Python2 脚本文件中包含了非 ASCII 字符时,一定要显式指定脚步文件编码格式,对于 Python3 因为默认的脚步文件编码格式就是 utf-8,所以没有这个问题(后面会有文章详细讨论这个问题)。

但是我们回头看下刚才的输出,结果显示为乱码。

乱码就涉及到另一个我们要说的不同点解释器字符编码,因为我们定义了 utf-8 格式读取脚步内容,但是因为 Python2.6 在 Windows 平台上,默认是使用 gbk 对字符进行 decode 输出,不信你看:

> python26

ActivePython 2.6.6.15 (ActiveState Software Inc.) based on

Python 2.6.6 (r266:84292, Aug 24 2010, 16:01:11) [MSC v.1500 32 bit (Intel)] on

win32

Type "help", "copyright", "credits" or "license" for more information.>>> s='中文'>>> s'\xd6\xd0\xce\xc4'>>> s.decode('gbk').encode('utf-8')'\xe4\xb8\xad\xe6\x96\x87'>>> print('\xd6\xd0\xce\xc4')

中文>>> print('\xe4\xb8\xad\xe6\x96\x87')

涓枃

完整描述下上面乱码出现的过程:

使用指定的脚本文件编码 utf-8 格式读取了「中文」,读取到的字符串内容为 ‘\xe4\xb8\xad\xe6\x96\x87’,然后输出时 Python2.6 的解释器使用默认解释器字符编码 gbk 格式对读取内容进行 encode 输出,但是之前 utf-8 是 3 个字节长度表示一个中文,而 gbk 是用 2 个字节长度来表示中文,所以之前的 2 个中文,在输出的时候就按照 3 个中文进行编码(encode),当然就乱码了,仔细看那个乱码,就是 3 个字。

我们再用代码验证下上面说的内容:

# -*- coding: utf-8 -*-import sys

print(sys.getdefaultencoding())

print('中文')

print('\xe4\xb8\xad\xe6\x96\x87')

print('\xe4\xb8\xad\xe6\x96\x87'.decode('gbk', 'ignore'))

print('\xd6\xd0\xce\xc4'.decode('gbk').encode('utf-8'))

print('中文'.decode('utf-8'))

print('\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))

print('\xd6\xd0\xce\xc4')

print('\xd6\xd0\xce\xc4'.decode('gbk'))

看看输出结果:

> python26 test.py

ascii

涓枃

涓枃

涓枃

涓枃

中文

中文

中文

中文

很明显 gbk 格式解码的十六进制字符正常输出为中文了,显式使用 utf-8 对 utf-8 格式的十六进制字符进行 decode 也输出正常了。

同理,还可以看到另外 2 个现象:

把 py 文件用 utf-8 格式存储,并且包含「中文」字样时,如果使用 gbk 格式打开,也是看到「中文」显示的乱码和上面程序输出的一致;

如果把 py 文件使用 gbk 格式存储,这时候 print('中文') 也显示正常了;

乱码的终极原因就是:对同一个字符串的 encode 和 decode 编码格式不一致。

上面说的这个问题,如果文件存储和脚本文件编码都使用 utf-8 时,使用 Python3.4 是没有问题的,因为 Python3 默认的解释器字符编码是 utf-8 了,默认就可以处理中文了。

总结下结论:

Python2 脚步文件尽量使用 gbk 格式存储;同理 Python3 脚步文件尽量使用 utf-8 格式存储;

Python2 脚步如果带有中文字符时,请务必在脚本开头声明能支持中文的脚本文件编码;

Python2 中对同一个字符串的 encode 和 decode 编码格式请保持一致;

说明:本次所有测试脚本文件均保存为 utf-8 格式

预约申请免费试听课

填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:python语言函数大总结!
下一篇:从Zero到Hero,一文掌握Python关键代码

2021年Python全套免费视频教程在哪里?

Python编程学习路线

Python最高有几级?

人工智能与语音遥控的区别?

  • 扫码领取资料

    回复关键字:视频资料

    免费领取 达内课程视频学习资料

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省