`

python编码问题

阅读更多

初学Python,遇到很多编码问题,记下来以免将来又忘了,很多东西不懂,都是属于不求甚解,乱下结论,但想到拿出来可以有热心同学指出错误所在,便厚起脸皮了……
首先需要了解Python中有两种字符串(严格地说,似乎不能这么叫)。一种是普通的str对象(每个字符用8bits表示),另一种是unicode字符串,它们可以相互转换。
首先打开pyshell,输入一段代码。

python 代码

view plaincopy to clipboardprint?
>>> a = "我"      
>>> b = unicode(a,"gb2312")      
>>> a.__class__      
<type 'str'>      
>>> b.__class__      
<type 'unicode'>      
>>>  
>>> a = "我"   
>>> b = unicode(a,"gb2312")   
>>> a.__class__   
<type 'str'>   
>>> b.__class__   
<type 'unicode'>   
>>> 

看出来了吧,两种字符串。
再来

python 代码
view plaincopy to clipboardprint?
>>> a      
'\xce\xd2'      
>>> b      
u'\u6211' 
>>> a   
'\xce\xd2'   
>>> b   
u'\u6211'
变量a是两个字符,b是一个unicode字符。
关于这两种字符串,Python文档-->LanguageReference-->DataModel-->The standard type hierarchy-->Sequences,有一些Strings,Unicode的描述。
至于

python 代码
view plaincopy to clipboardprint?
>>> z = u"我"      
>>> #这种代码,其实什么都不是。      
>>> z.__class__      
<type 'unicode'>      
>>> z      
u'\xce\xd2' 
>>> z = u"我"   
>>> #这种代码,其实什么都不是。   
>>> z.__class__   
<type 'unicode'>   
>>> z   
u'\xce\xd2'
看到了吧,这个奇怪的东西......
后来在WindowsXP、纯python命令行下试过,得出的结论不同,z的结果变成了u'\u6211',这里完全不应该在pyshell下作试验的,看来还有很多问题尚未理解清楚


再来看看encode,decode
什么情况用encode,什么情况又是decode呢,刚开始总是被搞昏。其实各种本地字符集的英文名是Coded Character Set,要转换为Coded,肯定是要encode了,同样,从里面解出来也应该叫decode……
decode就是把其他编码转换为unicode,等同于unicode函数;encode就是把unicode编码的字符串转换为特定编码。在pyshell里继续:
a是Str类型的,所以再用encode会报错。用print输出时会调用默认编码转换为系统编码?

python 代码
view plaincopy to clipboardprint?
>>> a.decode("gb2312")      
u'\u6211'      
>>> print a.decode("gb2312")      
我      
>>> a.encode("gb2312")      
Traceback (most recent call last):      
  File "<input>", line 1, in ?      
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128) 
>>> a.decode("gb2312")   
u'\u6211'   
>>> print a.decode("gb2312")   
我   
>>> a.encode("gb2312")   
Traceback (most recent call last):   
  File "<input>", line 1, in ?   
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)
b是unicode类型,打印时需要先encode(编码)成系统编码

python 代码
 view plaincopy to clipboardprint?
>>> print b.encode("gb2312")      
我      
>>> b.encode("gb2312")      
'\xce\xd2'      
>>> b.decode("gb2312")      
Traceback (most recent call last):      
  File "<input>", line 1, in ?      
UnicodeEncodeError: 'ascii' codec can't encode character u'\u6211' in position 0: ordinal not in range(128) 
>>> print b.encode("gb2312")   
我   
>>> b.encode("gb2312")   
'\xce\xd2'   
>>> b.decode("gb2312")   
Traceback (most recent call last):   
  File "<input>", line 1, in ?   
UnicodeEncodeError: 'ascii' codec can't encode character u'\u6211' in position 0: ordinal not in range(128)
python里默认的encode和decode是strict模式,所以会直接抛出Error,而Java里是默认replace模式,所以在处理servlet时经常会看到一串?????
在decode时传入第二个参数errors为'replace'可以和Java相同,但总是没成功,还不知道为什么

MySQLDb连接数据库的编码问题
试了很久,无论在connect的时候指定charset='utf8',还是使用set_character_set(),或者执行"SET NAMES UTF8",跟踪到character_set_name()方法返回的都是latin1...再跟代码,似乎就跑到mysql-api里去了,反正最后解决的办法也很简单,就是使用如下方式执行,而不要去拼sql语句……

python 代码
view plaincopy to clipboardprint?
>>> sql = "INSERT INTO t_user(name,nickname) values(%s,%s)"      
>>> param = ("张三","张三的昵称")      
>>> cursor.execute(sql,param) 
>>> sql = "INSERT INTO t_user(name,nickname) values(%s,%s)"   
>>> param = ("张三","张三的昵称")   
>>> cursor.execute(sql,param)
Python的国际化/i18n问题
使用gettext来实现。其实就是一个文本替换的方式,和java里用ResourceBundle、properties比较类似……
http://wiki.wxpython.org/index.cgi/RecipesI18n有一个recipe,不过代码很旧了,现在python里自带了pygettext.py和msgfmt.py
其实就是把http://blog.donews.com/limodou/archive/2004/06/15/28916.aspx的文章按自己思路组织了一下。
步骤:
1.导入gettext模块

python 代码
view plaincopy to clipboardprint?
import gettext      
gettext.install('i18ntest', './locale', unicode=True) 
import gettext   
gettext.install('i18ntest', './locale', unicode=True)
参数说明:
作用域:用于限定翻译文件的主名
路径:翻译文件所在路径
unicode:使用unicode

2.把代码里需要国际化的文本全部使用_("text")的形式进行替换

3.需要进行国际化处理时,调用

python 代码
view plaincopy to clipboardprint?
gettext.translation('i18ntest', './locale', languages=['cn']).install(True) 
gettext.translation('i18ntest', './locale', languages=['cn']).install(True)
来处理。

现在程序写好了,需要生成所需资源文件了:
1.调用python安装目录的 Tools/i18n/pygettext.py抽取所需翻译的模板
>>> pygettext.py path/to/yourfile.py
将生成一个名为messages.pot的文件
2.生成模板文件后,修改这个模板文件,其中的msgid为键值,对应你程序里写的文本,如:_("New File"),而msgstr为翻译后的值。还有就是注意修改文件头部分Content-Type的charset为合适的编码,比如utf8
3.编写好模板后,把扩展名修改为.po,运行Tools/i18n/msgfmt.py,生成二进制的资源文件
>>> msgfmt.py messages.po
将生成一个名为messages.mo的文件
4.把这个mo文件放在正确的位置.
比如你在程序中是这样写的:
gettext.install('i18ntest', './locale', unicode=True)
gettext.translation('i18ntest', './locale', languages=['cn']).install(True)
那么你的程序目录下需要存在./local/cn/LC_MESSAGES/i18ntest.mo
这样程序启动时就会读取这个资源文件,替换对应的文本,实现国际化了。
注意:如果使用utf格式保存,po文件不能有BOM头。cn目录是所对应的语言,LC_MESSAGES目录是gettext.py里要求的,mo文件必须和所定义的域同名,见
gettext.py的mofile = os.path.join(localedir, lang, 'LC_MESSAGES', '%s.mo' % domain)

学习资料

All About Python and Unicode http://boodebr.org/main/python/all-about-python-and-unicode
彻底了解python的编码问题 http://blog.csdn.net/iamjianglibo/archive/2007/02/07/1504819.aspx
Python中文问题研究 http://hi.baidu.com/daping_zhang/blog/item/09dda71ea9d7d21f4134173e.html
MySQLdb带中文参数的问题 http://bbs.chinaunix.net/archiver/?tid-833164.html
wxPython RecipesI18n http://wiki.wxpython.org/index.cgi/RecipesI18n
limodou的blog和ulipad/doc/i18n.htm
http://blog.donews.com/limodou/archive/2004/06/15/28916.aspx
http://blog.donews.com/limodou/archive/2004/06/15/28947.aspx
http://blog.donews.com/limodou/archive/2004/06/15/28961.aspx

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/flyingtimeice/archive/2009/06/19/4283145.aspx

分享到:
评论
1 楼 MegRyan 2009-12-14  
我用的版本是python2.6,其实这个问题在python3.0里已经解决了。

我开始的时候,也被这个问题搞的崩溃了。

这有篇很好的文章,可以明白这个问题:

(转):http://www.jb51.net/article/17560.htm

为什么会报错“UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)”?本文就来研究一下这个问题。
字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。

decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。

encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。

因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码

代码中字符串的默认编码与代码文件本身的编码一致。

如:s='中文'

如果是在utf8的文件中,该字符串就是utf8编码,如果是在gb2312的文件中,则其编码为gb2312。这种情况下,要进行编码转换,都需要先用decode方法将其转换成unicode编码,再使用encode方法将其转换成其他编码。通常,在没有指定特定的编码方式时,都是使用的系统默认编码创建的代码文件。

如果字符串是这样定义:s=u'中文'

则该字符串的编码就被指定为unicode了,即python的内部编码,而与代码文件本身的编码无关。因此,对于这种情况做编码转换,只需要直接使用encode方法将其转换成指定编码即可。

如果一个字符串已经是unicode了,再进行解码则将出错,因此通常要对其编码方式是否为unicode进行判断:

isinstance(s, unicode) #用来判断是否为unicode

用非unicode编码形式的str来encode会报错

如何获得系统的默认编码?

#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()

该段程序在英文WindowsXP上输出为:ascii

在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。

如在UliPad中运行如下代码:

s=u"中文"
print s

会提示:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)。这是因为UliPad在英文WindowsXP上的控制台信息输出窗口是按照ascii编码输出的(英文系统的默认编码是ascii),而上面代码中的字符串是Unicode编码的,所以输出时产生了错误。

将最后一句改为:print s.encode('gb2312')

则能正确输出“中文”两个字。

若最后一句改为:print s.encode('utf8')

则输出:\xe4\xb8\xad\xe6\x96\x87,这是控制台信息输出窗口按照ascii编码输出utf8编码的字符串的结果。

unicode(str,'gb2312')与str.decode('gb2312')是一样的,都是将gb2312编码的str转为unicode编码

使用str.__class__可以查看str的编码形式

相关推荐

    Python中文乱码

    综上所述,Python中文乱码问题主要源于字符编码的不匹配,通过正确识别和指定编码,可以避免大部分乱码情况的发生。在处理中文字符时,养成良好的编码习惯,统一使用UTF-8编码,可以显著减少乱码问题,提升开发效率...

    python编码问题的测试代码

    遵循最佳实践,如始终指定编码,保持编码一致性,以及正确处理Unicode和非Unicode字符串,可以帮助我们避免常见的乱码问题。通过分析`python_coding.py`和`hongloumeng.txt`,我们可以进一步加深对这些概念的理解。

    谈谈Python编码问题和U.ppt

    在IT领域,编程语言Python在处理文本数据时,特别是涉及到编码问题时,常常需要理解Unicode、...如果不一致,可能会导致乱码问题。因此,了解和正确使用各种编码在IT实践中至关重要,避免出现数据丢失或乱码的错误。

    python 中文乱码 问题深入分析.docx

    在 Python 中,中文乱码问题一直是一个让人头疼的问题,经常抛出编码转换的异常。那么,Python 中的 str 和 unicode 到底是什么东西呢? 首先,Python 中的 unicode 指的是 unicode 对象。例如,u'/u54c8/u54c8' ...

    PEP8Python 编码规范

    PEP8是关于Python编码风格的规范,而如何将英文文档转成中文应当是遵循翻译原则和文档规范的问题。所以,正确理解这部分内容应该是:PEP8指导如何书写整洁的Python代码,并且在必要时如何将文档和注释用中文书写,...

    google的python编码规范.pdf

    Google Python 编码规范 本文档是 Google 公司的 Python 编码规范,旨在为 Python 程序员提供一个详细的编码风格指南。该指南涵盖了 Python 语言规则、 Python 风格规则、代码编写风格、注释、类、字符串、TODO ...

    20180530_Python编码及中文乱码1

    Python 编码与解码详解 编码是将可读的字符转换为计算机内部表示的过程,而解码则是相反的过程,即将计算机内部的表示转换回可读的字符。...正确处理编码问题可以避免字符乱码,提高程序的兼容性和稳定性。

    Shannon_Python香农编码_python_shannon_香农编码_

    在Python中实现香农编码,首先需要统计字符的出现频率,这可以通过构建一个字典来完成。例如,遍历文本文件,对每个字符进行计数,得到一个键为字符、值为频率的字典。接着,可以使用哈夫曼树(也称为最优二叉树)来...

    Python编码规范.pdf

    使用 UTF-8 编码来保存 Python 代码文件,以避免编码错误和乱码。 导入 在使用导入语句时,需要遵守一定的规则,避免污染命名空间。建议使用 import 语句来导入模块,避免使用 from 语句来导入模块中的函数或变量。...

    python抓取并保存html页面时乱码问题的解决方法

    综上所述,解决Python抓取HTML页面时的乱码问题需要正确识别和处理编码。通过检测网页的编码、比较声明编码以及在必要时转换编码,可以有效地避免乱码的出现。此外,使用适当的库和模块(如`chardet`和`...

    python实现算术编码

    在这个Python实现中,我们将深入探讨算术编码的基本原理、Python编程实现的关键步骤以及如何进行编码和解码。 1. **算术编码的基本概念** 算术编码的核心思想是将输入符号的概率分布转化为一个连续的区间,通过...

    python解决中文乱码问题

    解决python中文乱码问题、首先发送请求,然后将请求返回的值传到coding(req)函数。

    python 文件读写 乱码

    在Python编程中,文件读写操作是非常常见的需求之一,尤其是在处理非英文或特殊字符时,经常会遇到乱码问题。本文将深入探讨Python中的文件读写以及如何正确处理编码问题,避免出现乱码的情况。 #### 一、Python...

    python编码规范.pdf

    适用于初学者的python规范。 “没有规矩不成方圆”。编程工作往往是一个团队协同进行,我们写出来的代码最终可能要提供给同事或其他人阅读,因而我们迫切需要一份一致的编码规范,以提高组内代码的可读性,同时加强...

    python2 编码问题的测试代码

    总的来说,理解Python2中的编码和解码机制,以及如何在处理文件和字符串时正确应用它们,对于避免中文乱码问题至关重要。通过细心处理编码转换,你可以确保Python程序能正确地处理各种语言的文本数据。

    python OpenCV imshow()中文乱码问题解决方法之一

    python OpenCV imshow()中文乱码问题解决方法之一

Global site tag (gtag.js) - Google Analytics