Python2.x中的编码问题

发布时间:2022-04-02 10:17:58 人气:80 作者:多测师

  1. str和unicode

  str和unicode都是basestring的子类。严格意义上说,str其实是字节串,它是unicode经过编码后的字节组成的序列。对UTF-8编码的str'汉'使用len()函数时,结果是3,因为实际上,UTF-8编码的'汉' == '\xE6\xB1\x89'。

  unicode才是真正意义上的字符串,对字节串str使用正确的字符编码进行解码后获得,并且len(u'汉') == 1。

  再来看看encode()和decode()两个basestring的实例方法,理解了str和unicode的区别后,这两个方法就不会再混淆了:

  13# coding: UTF-8

  u = u'汉'

  print repr(u) # u'\u6c49'

  s = u.encode('UTF-8')

  print repr(s) # '\xe6\xb1\x89'

  u2 = s.decode('UTF-8')

  print repr(u2) # u'\u6c49'

  # 对unicode进行解码是错误的

  # s2 = u.decode('UTF-8')

  # 同样,对str进行编码也是错误的

  # u2 = s.encode('UTF-8')

  需要注意的是,虽然对str调用encode()方法是错误的,但实际上Python不会抛出异常,而是返回另外一个相同内容但不同id的str;对unicode调用decode()方法也是这样。很不理解为什么不把encode()和decode()分别放在unicode和str中而是都放在basestring中,但既然已经这样了,我们就小心避免犯错吧。

  2. 字符编码声明

  源代码文件中,如果有用到非ASCII字符,则需要在文件头部进行字符编码的声明,如下:

  1#-*- coding: UTF-8 -*-

  实际上Python只检查#、coding和编码字符串,其他的字符都是为了美观加上的。另外,Python中可用的字符编码有很多,并且还有许多别名,还不区分大小写,比如UTF-8可以写成u8。参见http://docs.python.org/library/codecs.html#standard-encodings。

  另外需要注意的是声明的编码必须与文件实际保存时用的编码一致,否则很大几率会出现代码解析异常。现在的IDE一般会自动处理这种情况,改变声明后同时换成声明的编码保存,但文本编辑器控们需要小心 :)

Python2.x中的编码问题

  3. 读写文件

  内置的open()方法打开文件时,read()读取的是str,读取后需要使用正确的编码格式进行decode()。write()写入时,如果参数是unicode,则需要使用你希望写入的编码进行encode(),如果是其他编码格式的str,则需要先用该str的编码进行decode(),转成unicode后再使用写入的编码进行encode()。如果直接将unicode作为参数传入write()方法,Python将先使用源代码文件声明的字符编码进行编码然后写入。

  14# coding: UTF-8

  f = open('test.txt')

  s = f.read()

  f.close()

  print type(s) #

  # 已知是GBK编码,解码成unicode

  u = s.decode('GBK')

  f = open('test.txt', 'w')

  # 编码成UTF-8编码的str

  s = u.encode('UTF-8')

  f.write(s)

  f.close()

  另外,模块codecs提供了一个open()方法,可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述操作。相对内置的open()来说,这个方法比较不容易在编码上出现问题。

  20# coding: GBK

  import codecs

  f = codecs.open('test.txt', encoding='UTF-8')

  u = f.read()

  f.close()

  print type(u) #

  f = codecs.open('test.txt', 'a', encoding='UTF-8')

  # 写入unicode

  f.write(u)

  # 写入str,自动进行解码编码操作

  # GBK编码的str

  s = '汉'

  print repr(s) # '\xba\xba'

  # 这里会先将GBK编码的str解码为unicode再编码为UTF-8写入

  f.write(s)

  f.close()

  4. 与编码相关的方法

  sys/locale模块中提供了一些获取当前环境下的默认编码的方法。

  31# coding:gbk

  import sys

  import locale

  def p(f):

  print '%s.%s(): %s' % (f.__module__, f.__name__, f())

  # 返回当前系统所使用的默认字符编码

  p(sys.getdefaultencoding)

  # 返回用于转换Unicode文件名至系统文件名所使用的编码

  p(sys.getfilesystemencoding)

  # 获取默认的区域设置并返回元祖(语言, 编码)

  p(locale.getdefaultlocale)

  # 返回用户设定的文本数据编码

  # 文档提到this function only returns a guess

  p(locale.getpreferredencoding)

  # \xba\xba是'汉'的GBK编码

  # mbcs是不推荐使用的编码,这里仅作测试表明为什么不应该用

  print r"'\xba\xba'.decode('mbcs'):", repr('\xba\xba'.decode('mbcs'))

  #在笔者的Windows上的结果(区域设置为中文(简体, 中国))

  #sys.getdefaultencoding(): gbk

  #sys.getfilesystemencoding(): mbcs

  #locale.getdefaultlocale(): ('zh_CN', 'cp936')

  #locale.getpreferredencoding(): cp936

  #'\xba\xba'.decode('mbcs'): u'\u6c49'

  以上内容为大家介绍了Python2.x中的编码问题,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注多测师。https://www.e70w.com/xwzx/


返回列表
在线客服
联系方式

热线电话

17727591462

上班时间

周一到周五

二维码
线