文章介绍
用Python在控制台打印中文如何不会乱码,一直是困扰很多Pythoner的问题,甚至很多Python老手也经常犯难。原因就在于从一般网页、数据库或文本外来数据源上抓取过来的内容,需要经过正确的编解码才可以正常输出,而Python的编解码机制比较复杂,没有深入思考的话经常遇到调试错误。这篇文章介绍了最常见的几种输出中文的情况,编译平台为Windows控制台,Python版本为2.7.9
文章中一些内容参考了点击打开链接 感谢原作者分享。
预备知识
str和unicode
首先需要弄清楚str和unicode的区别。str是字节串,由unicode经过编码(encode)后的字节组成的。unicode才是真正意义上的字符串,由字符组成。在编程过程中,必须搞明白要处理的是str还是unicode, 使用对的处理方法(str.decode/unicode.encode)。一个简单的原则是:不要对str使用encode,不要对unicode使用decode(事实上str可以使用encode的,但不建议这么做,这里就不再赘述了。
用下面的代码判断是否为unicode/str:
<pre name="code" class="python">-*- coding=utf-8 -*-isinstance(u'哈哈你好', unicode)isinstance('哈哈你好',str)
打印结果均为True。
utf-8还是gbk
这两种都是中文的编码方式,选择其中哪一种都可以,但要注意的是必须同一项目中都统一使用,不能混合使用。
头部声明coding=utf-8, a = ‘中文‘ 其编码为utf-8
若头部声明coding=gb2312, a = ‘中文‘ 其编码为gbk
同一项目中所有源文件头部统一一个编码,并且声明的编码要和源文件保存的编码一致(编辑器相关)
PS:在源代码用作处理的硬编码字符串,统一用unicode
将其类型和源文件本身的编码隔离开, 独立无依赖方便流程中各个位置处理。
代码实现
1. 最简单的情况,直接在代码行输出中文,即中文字符串不是保存在变量里的,如下即可实现:
print u'哈哈你好'
这里是把中文字符串'哈哈你好'解码成unicode字符串了,如果直接print '哈哈你好'则会显示乱码
2. 如果中文字符串是保存在字符串变量里,则 按照下面的方式实现:
string='哈哈你好'print string.decode('UTF-8')
原理其实是跟第一种情况一样的,把中文字符串'哈哈你好'解码成unicode字符串了
3. 再复杂一点,中文字符串是保存在元组、列表或者字典里应该怎么输出呢?因为只有str对象才能调用decode方法,tuple/list/dict调用decode会报错,或许你会说把这些对象转换成str对象再调用decode,但那样很麻烦且程序效率不高。可以调用json模块的dumps方法,如下:
t_tuple=('哈哈','你好')t_list=['哈哈','你好']t_dict={1:'哈哈',2:'你好'}print json.dumps(t_tuple,encoding='UTF-8',ensure_ascii=False)print json.dumps(t_list,encoding='UTF-8',ensure_ascii=False)print json.dumps(t_dict,encoding='UTF-8',ensure_ascii=False)
要注意dumps方法里的两个参数
完整代码和打印结果
# -*- coding:UTF-8 -*-###测试python输出中文是否乱码import jsonprint u'哈哈你好'string='哈哈你好'print string.decode('UTF-8')<pre name="code" class="python">t_tuple=('哈哈','你好')t_list=['哈哈','你好']t_dict={1:'哈哈',2:'你好'}print json.dumps(t_tuple,encoding='UTF-8',ensure_ascii=False)print json.dumps(t_list,encoding='UTF-8',ensure_ascii=False)print json.dumps(t_dict,encoding='UTF-8',ensure_ascii=False)
在Windows控制台运行Python程序,输出结果为:
5种类型的中文输出均可以不乱码显示。
常见报错处理
1. win7控制台打印报错——UnicodeEncodeError: ‘gbk’ codec can’t encode character u’\u200e’ in position 43: illegal multibyte sequence
(1)出现UnicodeEncodeError –> 说明是Unicode编码时候的问题;
(2) ‘gbk’ codec can’t encode character –> 说明是将Unicode字符编码为GBK时候出现的问题;
此时,往往最大的可能就是,本身Unicode类型的字符中,包含了一些无法转换为GBK编码的一些字符。
解决办法是:
方案1:
在对unicode字符编码时,添加ignore参数,忽略无法无法编码的字符,这样就可以正常编码为GBK了。
对应代码为:
gbkTypeStr = unicodeTypeStr.encode(“GBK“, ‘ignore’);
方案2:
或者,将其转换为GBK编码的超集GB18030 (即,GBK是GB18030的子集)
gb18030TypeStr = unicodeTypeStr.encode(“GB18030“);
对应的得到的字符是GB18030的编码。