之前在CentOS 6下部署python3+tornado,处理编码格式为UTF-8的HTTP请求,但奇怪的发现,将bytes类型的请求内容decode的时候会报解码错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
同样的程序,在Windows和CentOS 7下都是正常的,只在CentOS 6下面有问题。
排查过程
我注意到,错误提示是ascii解码错误,难道是默认的编码方式不是utf-8?一看decode函数定义,默认编码是utf-8啊,而且在参数中手动指定为utf-8,一样的报这个错误。
把bytes的解码函数都试了,全都报这个错,然后突然想到既然是报值域不对,那是不是内容中没有中文就行了?试了一下全英文,果然可以执行通过了。
接下来就是搜索解决方案了,网上搜到的方法是,将python的系统默认编码设为utf8:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
然而,并没有用,因为我先查了一下默认的编码,本来就是utf-8
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
这就面临死结了,后来都忘了是怎么搜到的,说操作系统的编码也可能有影响,操作系统不支持utf-8的话,python也是没法编解码的。
好吧,locale命令看看,恩,全都是“en_US.UTF-8”,对的啊,是UTF-8,转码应该没问题的。
虽然说应该没问题,不过还是死马当活马医,改一下吧,设成“zh_CN.UTF-8”,恩,居然好了。。。
解决方案
编辑/etc/sysconfig/i18n,之前是:
LANG="en_US.UTF-8"
SUPPORTED="en_US.UTF-8:en_US:en"
SYSFONT="latarcyrheb-sun16"
对应的改成:
LANG="zh_CN.UTF-8"
SUPPORTED="zh_CN.UTF-8:zh_CN:zh"
SYSFONT="latarcyrheb-sun16"
程序就可以正常执行了。其他的编码应该也类似,可以通过查看/usr/share/i18n/SUPPORTED文件来看系统支持哪些编码,中文相关的有:
zh_CN.UTF-8 UTF-8
zh_CN.GB18030 GB18030
zh_CN.GBK GBK
zh_CN GB2312
问题虽然解决了,但是原因还是没想通,utf-8能不能编解码和区域设置为啥会有联系,英文的CentOS 7也没问题的,老的版本就没试了,只能理解成是CentOS 6特有的坑了。顺便吐槽一下,CentOS 6下面升级gcc-c++到4.8也超折腾,不能yum。
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-12/149721.htm