python3 django 中文乱码_python中文乱码

这篇博客详细讨论了Python3中处理中文乱码的常见问题和解决方案,包括SyntaxError、UnicodeDecodeError和UnicodeEncodeError。作者指出,Python内部使用Unicode编码,字符串输出乱码可能是由于IDE或控制台不支持特定编码导致。解决方法包括正确使用decode和encode函数,以及在输出时考虑不同编码。还提供了一个通用代码示例,并分析了向文件和网页请求内容时的编码转换问题。
摘要由CSDN通过智能技术生成

python中文乱码的问题

http://www.2cto.com/kf/201306/223110.html

在运行这样类似的代码:

#!/usr/bin/env python

s="中文"

print s

最近经常遇到这样的问题:

问题一:SyntaxError: Non-ASCII character '\xe4' in file E:\coding\python\Untitled 6.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

问题二:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 108: ordinal not in range(128)

问题三:UnicodeEncodeError: 'gb2312' codec can't encode character u'\u2014' in position 72366: illegal multibyte sequence

这些都是跟字符编码有关的问题,很郁闷,中文总是弄不出来,找了很多方案,这里有些是我前几天找到的一些方案,拿出来给大家分享一下哈

字符串在Python内部的表示是unicode 编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。

decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码。

encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。

在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。

如在UliPad中运行如下代码:

s=u"中文"

print s

会提示:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)。这是因为UliPad在英文WindowsXP 上的控制台信息输出窗口是按照ascii编码输出的(英文系统的默认编码是ascii),而上面代码中的字符串是Unicode编码的,所以输出时产生了错误。

将最后一句改为:print s.encode('gb2312')

则能正确输出“中文”两个字。

若最后一句改为:print s.encode('utf8')

则输出:\xe4\xb8\xad\xe6\x96\x87,这是控制台信息输出窗口按照ascii编码输出utf8编码的字符串的结果。

下面代码可能比较通用一些,如下:

[python] view plaincopyprint?

#!/usr/bin/env python

#coding=utf-8

s="中文"

if isinstance(s, unicode):

#s=u"中文"

print s.encode('gb2312')

else:

#s="中文"

print s.decode('utf-8').encode('gb2312')

#!/usr/bin/env python

#coding=utf-8

s="中文"

if isinstance(s, unicode):

#s=u"中文"

print s.encode('gb2312')

else:

#s="中文"

print s.decode('utf-8').encode('gb2312')

看看下面一段代码:

[python] view plaincopyprint?

#!/usr/bin/env python

#coding=utf-8

#python version:2.7.4

#system:windows xp

import httplib2

def getPageContent(url):

'''''

使用httplib2用编程的方式根据url获取网页内容

将bytes形式的内容转换成utf-8的字符串

'''

#使用ie9的user-agent,如果不设置user-agent将会得到403禁止访问

headers={'user-agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',

'cache-control':'no-cache'}

if url:

response,content = httplib2.Http().request(url,headers=headers)

if response.status == 200 :

return content

import sys

reload(sys)

sys.setdefaultencoding('utf-8')   #修改默认编码方式,默认为ascci

print sys.getdefaultencoding()

content = getPageContent("http://www.oschina.net/")

print content.decode('utf-8').encode('gb2312')

#!/usr/bin/env python

#coding=utf-8

#python version:2.7.4

#system:windows xp

import httplib2

def getPageContent(url):

'''

使用httplib2用编程的方式根据url获取网页内容

将bytes形式的内容转换成utf-8的字符串

'''

#使用ie9的user-agent,如果不设置user-agent将会得到403禁止访问

headers={'user-agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',

'cache-control':'no-cache'}

if url:

response,content = httplib2.Http().request(url,headers=headers)

if response.status == 200 :

return content

import sys

reload(sys)

sys.setdefaultencoding('utf-8')   #修改默认编码方式,默认为ascci

print sys.getdefaultencoding()

content = getPageContent("http://www.oschina.net/")

print content.decode('utf-8').encode('gb2312')

上面的代码的意思:向www.oschina.net网站请求他的主页,(如果直接是utf-8编码,不能输出中文)想将编码方式为utf-8转向gd2312,出现问题三

当我把它将print content.decode('utf-8').encode('gb2312')改成  print content.decode('utf-8').encode('gb2312', ‘ignore’)时,OK了,可以显示中文了,但不敢确定是否为全部,貌似只有部分吧,有些不能用gb2312编码

然而,当我把网站换成 www.soso.com时,不用转为gb2312,用utf-8即可正常显示中文

总结一下:

向文件直接输出ss会抛出同样的异常。在处理unicode中文字符串的时候,必须首先对它调用encode函数,转换成其它编码输出。这一点对各个环境都一样。在Python中,“str”对象就是一个字节数组,至于里面的内容是不是一个合法的字符串,以及这个字符串采用什么编码(gbk, utf-8, unicode)都不重要。这些内容需要用户自己记录和判断。这些的限制也同样适用于“unicode”对象。要记住“unicode”对象中的内容可绝对不一定就是合法的unicode字符串,我们很快就会看到这种情况。在windows的控制台上,支持gbk编码的str对象和unicode编码的unicode对象。

python 中文乱码问题深入分析

http://www.jb51.net/article/26543.htm

在本文中,以'哈'来解释作示例解释所有的问题,“哈”的各种编码如下:

1. UNICODE (UTF8-16),C854;

2. UTF-8,E59388;

3. GBK,B9FE。

一、python中的str和unicode一直以来,python中的中文编码就是一个极为头大的问题,经常抛出编码转换的异常,python中的str和unicode到底是一个什么东西呢?

在python中提到unicode,一般指的是unicode对象,例如'哈哈'的unicode对象为

u'\u54c8\u54c8'

而str,是一个字节数组,这个字节数组表示的是对unicode对象编码(可以是utf-8、gbk、cp936、GB2312)后的存储的格式。这里它仅仅是一个字节流,没有其它的含义,如果你想使这个字节流显示的内容有意义,就必须用正确的编码格式,解码显示。

例如:

62331a4fa265ddbd5405298742717511.png

对于unicode对象哈哈进行编码,编码成一个utf-8编码的str-s_utf8,s_utf8就是是一个字节数组,存放的就是'\xe5\x93\x88\xe5\x93\x88',但是这仅仅是一个字节数组,如果你想将它通过print语句输出成哈哈,那你就失望了,为什么呢?

因为print语句它的实现是将要输出的内容传送了操作系统,操作系统会根据系统的编码对输入的字节流进行编码,这就解释了为什么utf-8格式的字符串“哈哈”,输出的是“鍝堝搱”,因为 '\xe5\x93\x88\xe5\x93\x88'用GB2312去解释,其显示的出来就是“鍝堝搱”。这里再强调一下,str记录的是字节数组,只是某种编码的存储格式,至于输出到文件或是打印出来是什么格式,完全取决于其解码的编码将它解码成什么样子。

这里再对print进行一点补充说明:当将一个unicode对象传给print时,在内部会将该unicode对象进行一次转换,转换成本地的默认编码(这仅是个人猜测)

二、str和unicode对象的转换

str和unicode对象的转换,通过encode和decode实现,具体使用如下:

23ef5e23c5dfc2fb7934bac955e26667.png

将GBK'哈哈'转换成unicode,然后再转换成UTF8

三、Setdefaultencoding

252c9c0b460ff5d9e223c7a987055f01.png

如上图的演示代码所示:

当把s(gbk字符串)直接编码成utf-8的时候,将抛出异常,但是通过调用如下代码:

import sys

reload(sys)

sys.setdefaultencoding('gbk')

后就可以转换成功,为什么呢?在python中str和unicode在编码和解码过程中,如果将一个str直接编码成另一种编码,会先把str解码成unicode,采用的编码为默认编码,一般默认编码是anscii,所以在上面示例代码中第一次转换的时候会出错,当设定当前默认编码为'gbk'后,就不会出错了。

至于reload(sys)是因为Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入。

四、操作不同文件的编码格式的文件

建立一个文件test.txt,文件格式用ANSI,内容为:

abc中文

用python来读取

# coding=gbk

print open("Test.txt").read()

结果:abc中文

把文件格式改成UTF-8:

结果:abc涓枃

显然,这里需要解码:

# coding=gbk

import codecs

print open("Test.txt").read().decode("utf-8")

结果:abc中文

上面的test.txt我是用Editplus来编辑的,但当我用Windows自带的记事本编辑并存成UTF-8格式时,

运行时报错:

Traceback (most recent call last):

File "ChineseTest.py", line 3, in

print open("Test.txt").read().decode("utf-8")

UnicodeEncodeError: 'gbk' codec can't encode character u'\ufeff' in position 0: illegal multibyte sequence

原来,某些软件,如notepad,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。

因此我们在读取时需要自己去掉这些字符,python中的codecs module定义了这个常量:

# coding=gbk

import codecs

data = open("Test.txt").read()

if data[:3] == codecs.BOM_UTF8:

data = data[3:]

print data.decode("utf-8")

结果:abc中文

五、文件的编码格式和编码声明的作用

源文件的编码格式对字符串的声明有什么作用呢?这个问题困扰一直困扰了我好久,现在终于有点眉目了,文件的编码格式决定了在该源文件中声明的字符串的编码格式,例如:

str = '哈哈'

print repr(str)

a.如果文件格式为utf-8,则str的值为:'\xe5\x93\x88\xe5\x93\x88'(哈哈的utf-8编码)

b.如果文件格式为gbk,则str的值为:'\xb9\xfe\xb9\xfe'(哈哈的gbk编码)

在第一节已经说过,python中的字符串,只是一个字节数组,所以当把a情况的str输出到gbk编码的控制台时,就将显示为乱码:鍝堝搱;而当把b情况下的str输出utf-8编码的控制台时,也将显示乱码的问题,是什么也没有,也许'\xb9\xfe\xb9\xfe'用utf-8解码显示,就是空白吧。>_<

说完文件格式,现在来谈谈编码声明的作用吧,每个文件在最上面的地方,都会用# coding=gbk 类似的语句声明一下编码,但是这个声明到底有什么用呢?到止前为止,我觉得它的作用也就是三个:

声明源文件中将出现非ascii编码,通常也就是中文;

在高级的IDE中,IDE会将你的文件格式保存成你指定编码格式。

决定源码中类似于u'哈'这类声明的将‘哈'解码成unicode所用的编码格式,也是一个比较容易让人迷惑的地方,看示例:

#coding:gbk

ss = u'哈哈'

print repr(ss)

print 'ss:%s' % ss

将这个些代码保存成一个utf-8文本,运行,你认为会输出什么呢?大家第一感觉肯定输出的肯定是:

u'\u54c8\u54c8'

ss:哈哈

但是实际上输出是:

u'\u935d\u581d\u6431'

ss:鍝堝搱

为什么会这样,这时候,就是编码声明在作怪了,在运行ss = u'哈哈'的时候,整个过程可以分为以下几步:

1) 获取'哈哈'的编码:由文件编码格式确定,为'\xe5\x93\x88\xe5\x93\x88'(哈哈的utf-8编码形式)

2) 转成 unicode编码的时候,在这个转换的过程中,对于'\xe5\x93\x88\xe5\x93\x88'的解码,不是用utf-8解码,而是用声明编码处指定的编码GBK,将'\xe5\x93\x88\xe5\x93\x88'按GBK解码,得到就是''鍝堝搱'',这三个字的unicode编码就是u'\u935d\u581d\u6431',至止可以解释为什么print repr(ss)输出的是u'\u935d\u581d\u6431' 了。

好了,这里有点绕,我们来分析下一个示例:

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

ss = u'哈哈'

print repr(ss)

print 'ss:%s' % ss

将这个示例这次保存成GBK编码形式,运行结果,竟然是:

UnicodeDecodeError: 'utf8' codec can't decode byte 0xb9 in position 0: unexpected code byte

这里为什么会有utf8解码错误呢?想想上个示例也明白了,转换第一步,因为文件编码是GBK,得到的是'哈哈'编码是GBK的编码'\xb9\xfe\xb9\xfe',当进行第二步,转换成 unicode的时候,会用UTF8对'\xb9\xfe\xb9\xfe'进行解码,而大家查utf-8的编码表会发现,utf8编码表(关于UTF- 8解释可参见字符编码笔记:ASCII、UTF-8、UNICODE)中根本不存在,所以会报上述错误。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值