python编码小结

    最近被python2的编码弄得心烦意乱,决心花点时间搞懂这一块,省的以后遇到编码解码报错或是乱码再去查资料。以下是做的一些总结。

python编码顺序

    网上很多资料都在说python2编码应该如何如何,不过应该先分析一下哪里用到了编解码以及顺序是怎样的。
    首先,我们用编辑器写程序,源码文件在保存时会按照某种编码格式存储,而python解释器载入程序会按照默认的编码格式(python2是ASCII ,python3是utf-8)或是头部指定的编码方式去解码。
    其次,解释器也有默认编码,当程序中一些行为没有指定编码方式的时候就会用默认编码。
    最后,执行prnit 语句时,终端会用终端的编码格式去解码,然后打印出来。

头部声明编码格式

    最常见的错误就是python2默认编码是ascii码,程序中出现中文时就会报错。注意,只要出现中文就会报错,哪怕是注释中有中文,不是变量赋值或是调用encode() decode() 才报错。因为python解释器加载程序时,试图使用ascii码解码一些中文字符编码后的字节,无法解码产生错误。
    通常需要在头部以如下方式声明编码方式:

#coding=utf-8

    或是

# -*- coding:utf-8 -*-

    那么到底要声明什么编码方式呢?我们可以做个test,在test.py中输入以下两行:

# coding=utf-8
ustr=u'中文'

    然后将test.py保存为ascii格式,用python去运行test.py,哦豁,报错。

SyntaxError: (unicode error) ‘utf8’ codec can’t decode byte 0xd6 in position 0: invalid continuation byte

    因为文本虽然是用ascii码保存的,但通常编辑器会对中文字符做特殊处理,比如,edit plus会用gbk存储中文字符,而解释器加载时用的utf-8解码,自然报错了。再试试将第一行改为 # coding=gbk ,嗯, 不报错了。
    所以关键是,代码文件的保存格式要与文件头部声明的编码格式一致

python解释器的默认编码

    解释清楚这一部分必须要先明确python的unicode对象和str对象,前者可以看成货真价实的字符串对象,而后者虽然披着’str’的外衣但实际上是字节串。

    unicode对象转换为str对象使用encode()方法,相当于把字符串编码为字节流。相反的,str对象转换为unicode对象要用decode()方法,相当于把字节流解码为字符串。

    那么对一个str对象使用encode()方法会怎么样呢?可以试试。注意,本文之后的测试源文件都保存为utf-8。

# coding=utf-8
str_obj="中文"
str_obj.encode('gbk')

    哦豁,又报错了。

‘ascii’ codec can’t decode byte 0xe4 in position 0: ordinal not in range(128)

咦?哪来的ascii码?哦,这就是python默认编码用到的地方了。实际上对一个str对象encode,解释器会先用默认编码将str对象decode成一个unicode对象,然后再encode,过程相当于如下所示:

str_obj.decode('ascii').encode('gbk')


     可以修改默认编码方式如下, 但是真的不推荐修改,因为出错的根源并不在这里,而是混淆了encode() decode() 的用法。

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

终端编码

    在windows命令行执行 python test.py ,代码如下,猜猜看会发生什么?

# coding=utf-8
str_obj="中文"
uni_obj=u'中文'
print str_obj, repr(str_obj), str_obj.decode('utf-8') #涓枃 '\xe4\xb8\xad\xe6\x96\x87' 中文
print uni_obj, repr(uni_obj), uni_obj.encode('utf-8') #中文 u'\u4e2d\u6587' 涓枃

    其中 repr() 是一个将值转换为字符串的函数,且转换为供解释器读取的形式。这里用它来让我们知道解释器看到的到底是什么。
    str_ob是一个str对象,是一个字节串。对str使用print方法时,终端会用终端的编码格式进行解码(windows 命令行默认编码方式是gbk),然后打印出来。所以第一行乱码很容易解释了,因为str_obj是utf-8编码的字节,用gbk解码会产生乱码。
    而print 一个unicode对象时,会调用系统方法,编码方式为终端的编码格式,因此不会乱码。
    在windows命令行中可以用 chcp 指令查看和修改编码格式,默认是 chcp 936 ,即gbk编码。

注意事项总结总结

  1. 程序中出现字符串加前缀u 即程序内部使用unicode对象
  2. 从外部读如字节流的时候,一定要将这些字节流转化为unicode,在后面的代码中去处理unicode,而不是str
  3. 代码文件的保存格式要与文件头部声明的编码格式一致
  4. 不到必须时不要在你的程序里编解码Unicode字符,只在你要写入文件或者数据库或者网络时,才调用encode()函数和decode()函数



         以上都是本人的粗浅理解, 有些地方没有深入考究,也不知道理解得对不对。欢迎各位看客指正。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值