关于python中的编码问题汇总

本文详细讨论了Python中遇到的编码问题,包括默认编码设置、字符串连接时的编码转换,以及`sys.setdefaultencoding()`的使用。重点讲述了如何处理Unicode与UTF-8、GBK之间的转换,强调了理解和正确使用`decode`和`encode`方法的重要性。同时提醒开发者注意`print`函数可能引发的编码问题,并提供了判断文件和网页编码的方法。
摘要由CSDN通过智能技术生成

Python的编码问题基本是每个新手都会遇到的坎,但只要完全掌握了就跳过了这个坑,万变不离其中,这不最近我也遇到了这个问题,来一起看看吧。
事情的起因是review同事做的一个上传功能,看下面一段代码,self.fp是上传的文件句柄

fpdata = [line.strip().decode('gbk').encode('utf-8').decode('utf-8') for line in self.fp]
data = [''.join(['(', self.game, ',', ','.join(map(lambda x: "'%s'" % x, d.split(','))), ')']) for d in fpdata[1:]]

这段代码暴露了2个问题
1.默认编码使用gbk,为什么不用utf8?
2..encode(‘utf-8’).decode(‘utf-8’)完全没有必要,decode(‘gbk’)之后就已经是unicode了

我建议上传文本编码为utf8,于是代码变成这样?

fpdata = [line.strip() for line in self.fp if line.strip()]
data = [''.join(['(', self.game, ',', ','.join(map(lambda x: "'%s'" % x, d.split(','))), ')']) for d in fpdata[1:]]

可测试时报UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe4 in position 0: ordinal not in range(128),这个异常估计新手看到很头疼,这是什么意思呢?
就是说:在将ascii字符串decode为unicode时碰到了oxe4这个比特,这不在ascii的范围内,所有decode错误。

交代一下项目背景,我们用Python2.7,这是django工程,self.game是unicode对象,明白人一看就是sys.setdefaultencoding的问题,其实就是下面这个问题
无

哎呀,可我明明在settings.py中设置默认编码了呀,查看了一下,才发现闹了个笑话
无
看看到底发生了什么?由于fpdata都是utf8字符串,而self.game是unicode对象,字符串join时会将utf8字符串解码为unicode对象,但系统不知道你是utf8编码,默认使用ascii去解码,这出错也就不足为奇了。

这也是为什么在碰到编码问题时,老手建议增加sys.setdefaultencoding(“utf8”)操作,但为什么要加这么一个操作呢?我们从底层看看发生了什么?

当字符串连接unicode对象时,也就是a+b时,会调用PyString_Concat

# stringobject.c
void
PyString_Concat(register PyObject **pv, register PyObject *w)
{
    register PyObject *v;
    if (*pv == NULL)
        return;
    if (w == NULL || !PyString_Check(*pv)) {
        Py_CLEAR(*pv);
        return;
    }
    v = string_concat((PyStringObject *) *pv, w);
    Py_DECREF(*pv);
    *pv = v;
}

static PyObject *
string_concat(register PyStringObject *a, register PyObject *bb)
{
    register Py_ssize_t size;
    register PyStringObject *op;
    if (!PyString_Check(bb)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值