在本文中,以'哈'来解释作示例解释所有的问题,“哈”的各种编码如下:
1. UNICODE (UTF8-16),C854;
2. UTF-8,E59388;
3. GBK,B9FE。
一、python中的str和unicode
一直以来,python中的中文编码就是一个极为头大的问题,经常抛出编码转换的异常,python中的str和unicode到底是一个什么东西呢?
在python中提到unicode,一般指的是unicode对象,例如'哈哈'的unicode对象为
u'\u54c8\u54c8'
而str,是一个字节数组,这个字节数组表示的是对unicode对象编码(可以是utf-8、gbk、cp936、GB2312)后的存储的格式。这里它仅仅是一个字节流,没有其它的含义,如果你想使这个字节流显示的内容有意义,就必须用正确的编码格式,解码显示。
例如:

对于unicode对象哈哈进行编码,编码成一个utf-8编码的str-s_utf8,s_utf8就是是一个字节数组,存放的就是'\xe5\x93\x88\xe5\x93\x88',但是这仅仅是一个字节数组,如果你想将它通过print语句输出成哈哈,那你就失望了,为什么呢?
因为print语句它的实现是将要输出的内容传送了操作系统,操作系统会根据系统的编码对输入的字节流进行编码,这就解释了为什么utf-8格式的字符串“哈哈”,输出的是“鍝堝搱”,因为 '\xe5\x93\x88\xe5\x93\x88'用GB2312去解释,其显示的出来就是“鍝堝搱”。这里再强调一下,str记录的是字节数组,只是某种编码的存储格式,至于输出到文件或是打印出来是什么格式,完全取决于其解码的编码将它解码成什么样子。
这里再对print进行一点补充说明:当将一个unicode对象传给print时,在内部会将该unicode对象进行一次转换,转换成本地的默认编码(这仅是个人猜测)
二、str和unicode对象的转换
str和unicode对象的转换,通过encode和decode实现,具体使用如下:

将GBK'哈哈'转换成unicode,然后再转换成UTF8
三、Setdefaultencoding

如上图的演示代码所示:
当把s(gbk字符串)直接编码成utf-8的时候,将抛出异常,但是通过调用如下代码:
import sys
reload(sys)
sys.setdefaultencoding('gbk')
后就可以转换成功,为什么呢?在python中str和unicode在编码和解码过程中,如果将一个str直接编码成另一种编码,会先把str解码成unicode,采用的编码为默认编码,一般默认编码是anscii,所以在上面示例代码中第一次转换的时候会出错,当设定当前默认编码为'gbk'后,就不会出错了。
至于reload(sys)是因为Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入。
四、操作不同文件的编码格式的文件
建立一个文件test.txt,文件格式用ANSI,内容为:
abc中文
用python来读取
# coding=gbk
print open("Test.txt").read()
结果:abc中文
把文件格式改成UTF-8:
结果:abc涓枃
显然,这里需要解码:
# coding=gbk
import codecs
print open("Test.txt").read().decode("utf-8")
结果:abc中文
上面的test.txt我是用Editplus来编辑的,但当我用Windows自带的记事本编辑并存成UTF-8格式时,
运行时报错:
Traceback (most recent call last):
File "ChineseTest.py", line 3, in
print open("Test.txt").read().decode("utf-8")
UnicodeEncodeError: 'gbk' codec can't encode character u'\ufeff' in position 0: illegal multibyte sequence
原来,某些软件,如notepad,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。
因此我们在读取时需要自己去掉这些字符,python中的codecs module定义了这个常量:
# coding=gbk
import codecs
data = open("Test.txt").read()
if data[:3] == codecs.BOM_UTF8:
data = data[3:]
print data.decode("utf-8")
结果:abc中文
五、文件的编码格式和编码声明的作用
源文件的编码格式对字符串的声明有什么作用呢?这个问题困扰一直困扰了我好久,现在终于有点眉目了,文件的编码格式决定了在该源文件中声明的字符串的编码格式,例如:
str = '哈哈'
print repr(str)
a.如果文件格式为utf-8,则str的值为:'\xe5\x93\x88\xe5\x93\x88'(哈哈的utf-8编码)
b.如果文件格式为gbk,则str的值为:'\xb9\xfe\xb9\xfe'(哈哈的gbk编码)
在第一节已经说过,python中的字符串,只是一个字节数组,所以当把a情况的str输出到gbk编码的控制台时,就将显示为乱码:鍝堝搱;而当把b情况下的str输出utf-8编码的控制台时,也将显示乱码的问题,是什么也没有,也许'\xb9\xfe\xb9\xfe'用utf-8解码显示,就是空白吧。>_<
说完文件格式,现在来谈谈编码声明的作用吧,每个文件在最上面的地方,都会用# coding=gbk 类似的语句声明一下编码,但是这个声明到底有什么用呢?到止前为止,我觉得它的作用也就是三个:
- 声明源文件中将出现非ascii编码,通常也就是中文;
- 在高级的IDE中,IDE会将你的文件格式保存成你指定编码格式。
- 决定源码中类似于u'哈'这类声明的将‘哈'解码成unicode所用的编码格式,也是一个比较容易让人迷惑的地方,看示例:
#coding:gbk
ss = u'哈哈'
print repr(ss)
print 'ss:%s' % ss
将这个些代码保存成一个utf-8文本,运行,你认为会输出什么呢?大家第一感觉肯定输出的肯定是:
u'\u54c8\u54c8'
ss:哈哈
但是实际上输出是:
u'\u935d\u581d\u6431'
ss:鍝堝搱
为什么会这样,这时候,就是编码声明在作怪了,在运行ss = u'哈哈'的时候,整个过程可以分为以下几步:
1) 获取'哈哈'的编码:由文件编码格式确定,为'\xe5\x93\x88\xe5\x93\x88'(哈哈的utf-8编码形式)
2) 转成 unicode编码的时候,在这个转换的过程中,对于'\xe5\x93\x88\xe5\x93\x88'的解码,不是用utf-8解码,而是用声明编码处指定的编码GBK,将'\xe5\x93\x88\xe5\x93\x88'按GBK解码,得到就是''鍝堝搱'',这三个字的unicode编码就是u'\u935d\u581d\u6431',至止可以解释为什么print repr(ss)输出的是u'\u935d\u581d\u6431' 了。
好了,这里有点绕,我们来分析下一个示例:
#-*- coding:utf-8 -*-
ss = u'哈哈'
print repr(ss)
print 'ss:%s' % ss
将这个示例这次保存成GBK编码形式,运行结果,竟然是:
UnicodeDecodeError: 'utf8' codec can't decode byte 0xb9 in position 0: unexpected code byte
这里为什么会有utf8解码错误呢?想想上个示例也明白了,转换第一步,因为文件编码是GBK,得到的是'哈哈'编码是GBK的编码'\xb9\xfe\xb9\xfe',当进行第二步,转换成 unicode的时候,会用UTF8对'\xb9\xfe\xb9\xfe'进行解码,而大家查utf-8的编码表会发现,utf8编码表(关于UTF- 8解释可参见字符编码笔记:ASCII、UTF-8、UNICODE)中根本不存在,所以会报上述错误。
分享到:
相关推荐
Python-mode自动处理代码的缩进,遵循Python的PEP8编码规范,使得代码保持良好的格式,提高可读性。 4. **代码检查**: 插件集成了一些静态代码分析工具,如pylint,可以在编写代码时实时检查语法错误和潜在问题...
MySQL-python是Python编程语言与MySQL数据库之间的一个接口,它允许Python开发者方便地访问和操作MySQL数据库。这个压缩包包含了两个版本的MySQL-python安装程序:一个适用于32位系统(MySQL-python-1.2.3.win32-py...
Python 2.7.15 是 Python 语言的一个重要版本,尤其对于那些仍然依赖 Python 2.x 版本的项目而言。AMD64 表示这个版本是为 64 位架构设计的,适用于使用 AMD 或 Intel 64 位处理器的计算机。在Windows系统上,`.msi`...
11. **附录**:包括Python的版本历史、编码规范(PEP 8)和其他有用的资源。 这个PDF文档对于Python学习者和开发者来说是宝贵的参考资料,无论你是新手还是经验丰富的开发者,都可以从中找到你需要的信息。通过阅读...
同时,熟悉Python的最佳实践,如PEP 8编码规范,是提升代码可读性和团队协作的关键。 总之,"python-3.7.7-amd64"压缩包提供了一个完整的Python 3.7.7环境,适用于AMD64架构的计算机,包含了进行Python开发所需的...
1. **代码编辑器**:org-netbeans-modules-python-editor.nbm 提供了对Python语法高亮、自动完成、错误检测和代码折叠等功能,提高了编码效率。 2. **项目管理**:org-netbeans-modules-python-project.nbm 使得...
2. **丰富的API**:Python-PIME提供了一系列API,开发者可以轻松地调用来实现各种输入法功能,如拼音解析、五笔编码、自定义规则等。 3. **跨平台兼容性**:尽管主要针对Windows平台,Python-PIME也尽可能地考虑了...
Python-Evolute是一个专门针对数值优化问题的Python进化算法工具箱。它为用户提供了一个简洁而易用的框架,便于快速实现和实验各种进化算法。在机器学习和数据分析领域,优化问题常常出现,例如寻找模型参数的最佳...
8. `python-chardet-2.2.1-1.el7_1.noarch.rpm`:字符编码检测库,帮助处理多语言编码问题。 9. `lvm2-python-libs-2.02.177-4.el7.x86_64.rpm`:LVM2(逻辑卷管理)的Python库,用于管理系统中的LVM配置。 10. `...
这个版本在Python 3.7系列中属于维护更新,旨在提升性能、修复已知问题并增强其兼容性。下面我们将深入探讨Python 3.7.8中的关键知识点: 1. **类型注解(Type Annotations)**:Python 3.7引入了正式的类型注解,...
字符串处理上,Python 2有str和unicode两种类型,而Python 3统一为str类型,采用Unicode编码;异常处理语法也有所不同,Python 3使用as关键字来指定变量名,而Python 2则使用":"。 2. **Python 2.7.13的特点**: -...
3. **Unicode支持**:Python 2.7.8进一步完善了Unicode处理,尤其是在字符串操作和文件I/O方面,增强了对多种字符编码的支持。 4. **异常处理**:Python 2.7.8对异常处理机制进行了一些调整,使得错误信息更清晰,...
1. **编码(Encoding)**: 使用`cjson.encode()`方法可以将Python对象编码为JSON字符串,如`json_str = cjson.encode(my_dict)`。 2. **解码(Decoding)**: `cjson.decode()`方法用于将JSON字符串解析为Python对象...
MySQL-python-1.2.3.win-amd64-py2.7 是一个适用于Python 2.7版本的MySQL数据库连接器,专为64位Windows操作系统设计。这个压缩包包含了一个可执行文件,用于安装MySQL的Python适配器,使得Python程序能够方便地与...
- **安全编码实践**:Python 3.11 可能强调了安全编码的最佳实践,比如输入验证和预防 SQL 注入等。 - **加密库更新**:可能升级了内置的加密库,以保持与最新安全标准的兼容。 6. **异步编程**: - **asyncio ...
5. **错误处理**:库中通常会包含对异常的妥善处理,比如在执行命令时遇到问题,Python-hotredis 可能会抛出易于理解和处理的 Python 异常。 6. **性能优化**:Python-hotredis 可能会进行一些底层优化,以提高与 ...
- MySQL-python库处理字符编码问题,如设置字符集以确保数据的正确传输和存储。 11. **数据库版本兼容性**: - MySQL-python适用于多种版本的MySQL数据库,但不同的版本可能存在兼容性问题,需要关注库的更新与...
5. **更好的错误消息**:许多错误消息得到了改善,提供了更详细的上下文信息,帮助开发者更快地定位问题。 安装Python 3.7.4-amd64.exe的过程相当直观: 1. **下载安装包**:从Python官方网站或可信的第三方源下载...
Python Opus 是一个用于处理 Opus 音频格式的 Python 库,它允许开发者在 Python 环境中实现音频的编码、解码以及相关的处理功能。Opus 是一种高效且高质量的音频编解码器,特别适用于网络传输,如 VoIP、流媒体和...