我曾经在
深入浅出java中文问题系列中研究过java的中文问题,现在中文问题已经很少羁绊我在java世界中漫游的脚步了。最近,对Python产生了浓厚的兴趣,谁知道跟中文问题这个老朋友又一次不期而遇。看来,在代码世界中,中文问题会在很长一段时间里跟我们形影不离。这也难怪,谁让当初发明计算机的不是我们中国人呢,否则,现在全世界的计算机都支持而且必须支持GBK,这样,写这样文章的人就不会是我了,而是大洋彼岸的一个金发碧眼的程序员,而且标题也相应改为 “studying the english problem in '大蟒' ”。。哈哈
YY而已,还是面对现实问题吧。相对java而言,中文问题在Python中的表现更为激烈。“激烈”的意思不是说更为严重或者说难于解决,只是Python对于decode&encode错误的默认处理方式为strict,也就是直接报错,而java使用replace的方式来处理了,因此java出现中文问题后会打印出很多"??"。此外,Python的默认的encoding是ASCII,而java的默认encoding跟操作系统的encoding是一致的。在这一点上,我觉得java更为合理,这样对程序员更为友好,也减少了newbies 开始时的挫折感,是有利于语言的推广的。但是,Python也有它的道理,毕竟ASCII是唯一的全世界所有平台都支持的字符集,而且问题始终是问题,始终会出现的,逃避它还不如早点面对它。
好了,说了这么多,该说说Python中中文问题的症状了。在这之前,我们先要了解Python中有两种字符串,分别是一般的字符串(每个字符用8 bits表示)和Unicode字符串(每个字符用一个或者多个字节表示),它们可以相互转换。关于Unicode,Joel Spolsky 在
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) 中有生动的说明,Jason Orendorff 在
Unicode for programmers 有着更为全面的描述,在此我就不再多说什么了。来看下面的代码:
python 代码
运行上述代码,Python会给出下面的错误提示
- SyntaxError: Non-ASCII character '\xd6' in file G:\workspace\chinese_problem\src\test.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
说是遇到非ASCII字符了,并让我们参考pep-0263。PEP-0263(Python Enhancement Proposal)上面说得很清楚了,Python也意识到了国际化问题,并提出了解决方案。根据提案上面的要求,我们有如下代码
python 代码
-
- print "-------------code 1----------------"
- a = "中文a我爱你"
- print a
- print a.find("我")
- b = a.replace("爱", "喜欢")
- print b
- print "--------------code 2----------------"
- x = "中文a我爱你"
- y = unicode(x, "gb2312")
- print y.encode("gb2312")
- print y.find(u"我")
- z = y.replace(u"爱", u"喜欢")
- print z.encode("gb2312")
- print "---------------code 3----------------"
- print y
程序运行的结果如下:
- -------------code 1----------------
- 中文a我爱你
- 5
- 中文a我喜欢你
- --------------code 2----------------
- 中文a我爱你
- 3
- 中文a我喜欢你
- ---------------code 3----------------
- Traceback (most recent call last):
- File "G:\Downloads\eclipse\workspace\p\src\hello.py", line 16, in <module>
- print y
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
我们可以看到,通过引入编码声明,我们可以正常地在使用中文了,而且在code 1和2中,控制台也能正确的把中文打印出来。但是,很明显,上面的代码也反映出了不少的问题:
1、code 1 和 2在使用print时采用了不同的方式,1是直接print,而2在print之前先进行编码
2、code 1 和 2中在同样的字符串查找同一个字符“我”,得出的结果不一样(分别是5和3)
3、code 3 中直接打印unicode字符串 y时出现错误(这也是为什么code 2中要先进行编码的原因)
为什么?为什么?我们可以先在脑海中模拟一下我们使用Python的流程:首先,我们先用编辑器编写好源代码,保存成文件。如果源代码中有编码声明而且用的编辑器支持该语法,那么该文件就以相应的编码方式保存在磁盘中。注意:编码声明和源文件的编码不一定是一致的,你完全可以在编码声明中声明编码为UTF-8,但是用GB2312来保存源文件。当然,我们不可能自寻烦恼,故意写错,而且好的IDE也能强制保证两者的一致性,但是,如果我们用记事本或者EditPlus等编辑器来编写代码的话,一不小心就会出现这种问题的。
得到一个.py文件后,我们就可以运行它了,这是,我们就把代码交给Python解析器来完成解析工作。解析器读入文件时,先解析文件中的编码声明,我们假设文件的编码为gb2312,那么先将文件中的内容由gb2312转换成Unicode,然后再把这些Unicode转换为UTF-8格式的字节串。完成这一步骤后,解析器把这些UTF-8字节串分段,解析。如果遇到使用Unicode字符串,那么就使用相应的UTF-8字节串创建Unicode字符串,如果程序中使用的是一般的字符串,那么解析器先将UTF-8字节串通过Unicode转换成相应编码(这里就是gb2312编码)的字节串,并用其创建一般的字符串对象。也就是说,Unicode字符串跟一般字符串在内存中的存放格式是不一样的,前者使用UTF-8的格式,后者使用GB2312格式。
好了,内存中的字符串存放格式我们知道了,下面我们要了解print的工作方式。print其实只是负责把内存中相应的字节串交给操作系统,让操作系统相应的程序(譬如cmd窗口)进行显示。这里有两种情况:
1、若字符串是一般的字符串,那么print只需把内存中相应的字节串推送给操作系统。如例子中的code 1。
2、如果字符串是Unicode字符串,那么print在推送之前先进行相应的encode:我们可以显示使用Unicode的encode方法使用合适的编码方式来编码(例子中code 2),否则Python使用默认的编码方式进行编码,也就是ASCII(例子中的code 3)。当然ASCII是不可能正确编码中文的,因此Python报错。
至此,上面的三个问题我们已经可以解析第一和第三个了。至于第二个问题,因为Python中有两种字符串,一般字符串和Unicode字符串,两者都有各自的字符处理方法。对于前者,方法是以字节的方式进行的,而且在GB2312中,每个汉字占用两个字节,因此得到的结果是5;对于后者,也就是Unicode字符串,所有字符都是统一看待的,因此得到3。
虽然上面只提到了控制台程序的中文问题,但是文件读写以及网络传输中出现的中文问题在原理上都是类似的。Unicode的出现可以很大程度上解决软件的国际化问题,同时Python为Unicode提供了极为良好的支持,因此,我建议大家在编写Python的程序时,都统一使用Unicode方式。保存文件时使用UTF-8的编码方式。How to Use UTF-8 with Python有详细的描述,大家可以参考一下。
Python中能导致出现中文问题的地方还很多,譬如文件的读写,网络数据的传输等,希望大家能多多交流,共同解决这些问题。
分享到:
相关推荐
本篇文章将深入探讨如何使用Python库`xlrd`来读取Excel文件,以及如何将中文字符转换为英文并进行特定格式的处理。 首先,`xlrd`是一个流行的Python库,用于读取Excel文件。它支持多种Excel文件格式,包括.xls和....
《Learning Python中文版》是一本旨在帮助读者入门Python编程语言的书籍。这本书详细介绍了Python的基础知识,适合初学者和希望提高编程技能的读者。Python是一种自由的开放源码的解释性语言,它设计的初衰就是追求...
《Programming Python 中文第四版》是一本深入介绍Python编程的权威指南,专为那些希望学习或深化Python编程技能的人设计。这本书的第四版更新了内容,涵盖了最新的Python版本特性,确保读者能掌握当前最前沿的...
在Python编程中,汉字排序通常是一项挑战,因为汉字本身无法按照字母顺序进行排列。然而,通过将汉字转换为其对应的拼音,我们可以实现...通过理解汉字与拼音的关系,我们可以扩展Python的功能,更好地处理中文文本。
《Python中文自然语言处理基础与实战》是一本深入浅出的教程,涵盖了使用Python进行NLP工作的各个方面。在本文中,我们将详细探讨该领域的重要概念、工具和技术,并结合实际案例来深化理解。 首先,让我们从Python...
《深入理解Python中文版高清版》是一本专为Python爱好者和开发者准备的深入学习书籍,旨在帮助读者全面、深入地掌握Python编程语言的核心概念和技术。这本书涵盖了Python的基础语法、高级特性、面向对象编程、异常...
总的来说,"Python-中文文档"是一份全面的教程,不仅涵盖了Python的基本语法和核心概念,还深入探讨了进阶主题,对于希望提升Python技能的人来说,是一份宝贵的资源。通过系统学习,你可以更好地理解Python的工作...
Python 从新手到高手 Dive Into Python 是为有经验的程序员编写的一本 Python 书。 1.在多个平台安装Python 2.第一个Python程序 3.内置数据类型 4.自省的威力 5.对象和面向对象 6.异常和文件处理 7.正则表达式 8....
本篇将深入探讨如何使用Python来生成汉字验证码。 首先,我们需要了解汉字验证码的基本构成。一个典型的汉字验证码通常包含1-4个随机汉字,有时还会加入数字或字母以增加复杂性。为了生成这样的验证码,我们需要...
《Dive Into Python3》和《深入Python3》是两本深受Python爱好者欢迎的书籍,分别提供了英文和中文的学习资源,旨在帮助读者全面理解和掌握Python3编程语言。这两本书覆盖了Python3的基础语法、高级特性以及实际应用...
综上所述,《OpenCV-Python 中文教程》是一本面向Python开发者的实用指南,旨在帮助读者迅速掌握OpenCV,利用其强大的图像处理能力解决实际问题。由于内容基于OpenCV的最新版本,确保了教程的时效性,使得读者能够...
Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆 于1990 年代初设计,作为一门叫做ABC语言的替代品。 Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言...
《深入 Python 中文版》是一本专为Python初学者及进阶者设计的教程,它提供了全面且深入的Python知识,旨在帮助读者更好地理解和运用这门强大的编程语言。书籍涵盖的内容广泛,包括基础语法、数据结构、函数、类与...
根据提供的信息,我们可以了解到《Head First Python 中文》是一本被高度评价的书籍,它主要聚焦于Python编程语言的学习。接下来,我们将详细探讨与这本书及其主题相关的知识点。 ### Python编程语言简介 Python是...
- **案例研究**:通过具体案例展示Python3在实际项目中的应用,帮助读者理解如何将所学知识应用于解决实际问题。 综上所述,《深入Python3中文教程》是一本面向具有一定Python2基础的读者的高级教程,旨在帮助他们...
本篇文章将深入探讨Python环境下如何实现汉字到拼音的转换,并介绍相关工具和使用方法。 标题提及的“Python-汉字拼音转换工具”是一种能够帮助开发者将汉字转化为拼音的Python库。这种功能在多个场景下非常实用,...
本项目将探讨如何使用Python实现QANet模型,并应用于DUREADER中文机器阅读理解数据集。 DUREADER是阿里云推出的一个大规模中文机器阅读理解数据集,涵盖了多种阅读理解任务类型,如问答、对话式问答等,旨在推动...
标题中提到的"PYTHON自然语言处理中文",意味着我们将探讨的是Python在NLP领域的应用,特别是对于中文文本的处理。中文自然语言处理相较于英文有其特殊性,比如中文没有明显的空格分隔单词,这对分词造成了挑战。...
本文将深入探讨一个基于Python的中文情感分析程序,它利用深度学习技术对中文文本进行情感倾向判断,旨在帮助用户理解大量中文评论数据中的情感趋势。 首先,我们要了解什么是情感分析。情感分析,又称为情绪挖掘,...