设为首页 收藏本站
查看: 992|回复: 0

[经验分享] python字符编码详解

[复制链接]

尚未签到

发表于 2018-8-10 07:20:57 | 显示全部楼层 |阅读模式
需要注意的是,虽然对str调用encode()方法是错误的,但实际上Python不会抛出异常,而是返回另外一个相同内容但不同id的str;对unicode调用decode()方法也是这样。很不理解为什么不把encode()和decode()分别放在unicode和str中而是都放在basestring中,但既然已经这样了,我们就小心避免犯错吧。  2.2. 字符编码声明
  源代码文件中,如果有用到非ASCII字符,则需要在文件头部进行字符编码的声明,如下:
  #-*- coding: UTF-8 -*-
  实际上Python只检查#、coding和编码字符串,其他的字符都是为了美观加上的。另外,Python中可用的字符编码有很多,并且还有许多别名,还不区分大小写,比如UTF-8可以写成u8。参见[http://docs.python.org/library/codecs.html#standard-encodings]。
  另外需要注意的是声明的编码必须与文件实际保存时用的编码一致,否则很大几率会出现代码解析异常。现在的IDE一般会自动处理这种情况,改变声明后同时换成声明的编码保存,但文本编辑器控们需要小心 :)
  2.3. 读写文件
  内置的open()方法打开文件时,read()读取的是str,读取后需要使用正确的编码格式进行decode()。write()写入时,如果参数是unicode,则需要使用你希望写入的编码进行encode(),如果是其他编码格式的str,则需要先用该str的编码进行decode(),转成unicode后再使用写入的编码进行encode()。如果直接将unicode作为参数传入write()方法,Python将先使用源代码文件声明的字符编码进行编码然后写入。
  # coding: UTF-8
  f = open('test.txt')
  s = f.read()
  f.close()
  print type(s) # <type 'str'>
  # 已知是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()来说,这个方法比较不容易在编码上出现问题。
  # coding: GBK
  import codecs
  f = codecs.open('test.txt', encoding='UTF-8')
  u = f.read()
  f.close()
  print type(u) # <type 'unicode'>
  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()
  2.4. 与编码相关的方法
  sys/locale模块中提供了一些获取当前环境下的默认编码的方法。
  # 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'
  3.一些建议
  3.1. 使用字符编码声明,并且同一工程中的所有源代码文件使用相同的字符编码声明。
  这点是一定要做到的。
  3.2. 抛弃str,全部使用unicode。
  按引号前先按一下u最初做起来确实很不习惯而且经常会忘记再跑回去补,但如果这么做可以减少90%的编码问题。如果编码困扰不严重,可以不参考此条。
  3.3. 使用codecs.open()替代内置的open()。
  如果编码困扰不严重,可以不参考此条。
  3.4. 绝对需要避免使用的字符编码:MBCS/DBCS和UTF-16。
  这里说的MBCS不是指GBK什么的都不能用,而是不要使用Python里名为’MBCS’的编码,除非程序完全不移植。
  Python中编码’MBCS’与’DBCS’是同义词,指当前Windows环境中MBCS指代的编码。Linux的Python实现中没有这种编码,所以一旦移植到Linux一定会出现异常!另外,只要设定的Windows系统区域不同,MBCS指代的编码也是不一样的。分别设定不同的区域运行2.4小节中的代码的结果:
  #中文(简体, 中国)
  #sys.getdefaultencoding(): gbk
  #sys.getfilesystemencoding(): mbcs
  #locale.getdefaultlocale(): ('zh_CN', 'cp936')
  #locale.getpreferredencoding(): cp936
  #'\xba\xba'.decode('mbcs'): u'\u6c49'
  #英语(美国)
  #sys.getdefaultencoding(): UTF-8
  #sys.getfilesystemencoding(): mbcs
  #locale.getdefaultlocale(): ('zh_CN', 'cp1252')
  #locale.getpreferredencoding(): cp1252
  #'\xba\xba'.decode('mbcs'): u'\xba\xba'
  #德语(德国)
  #sys.getdefaultencoding(): gbk
  #sys.getfilesystemencoding(): mbcs
  #locale.getdefaultlocale(): ('zh_CN', 'cp1252')
  #locale.getpreferredencoding(): cp1252
  #'\xba\xba'.decode('mbcs'): u'\xba\xba'
  #日语(日本)
  #sys.getdefaultencoding(): gbk
  #sys.getfilesystemencoding(): mbcs
  #locale.getdefaultlocale(): ('zh_CN', 'cp932')
  #locale.getpreferredencoding(): cp932
  #'\xba\xba'.decode('mbcs'): u'\uff7a\uff7a'
  可见,更改区域后,使用mbcs解码得到了不正确的结果,所以,当我们需要使用’GBK’时,应该直接写’GBK’,不要写成’MBCS’。
  UTF-16同理,虽然绝大多数操作系统中’UTF-16’是’UTF-16-LE’的同义词,但直接写’UTF-16-LE’只是多写3个字符而已,而万一某个操作系统中’UTF-16’变成了’UTF-16-BE’的同义词,就会有错误的结果。实际上,UTF-16用的相当少,但用到的时候还是需要注意。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-549347-1-1.html 上篇帖子: python基础:装饰器 下篇帖子: python入门(四)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表