为什么Python使用过程中会出现各式各样的乱码问题,明明是中文字符却显示成“\xe4\xb8\xad\xe6\x96\x87”的形式?

为什么会报错“UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)”?本文就来研究一下这个问题。

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

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

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

因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码

代码中字符串的默认编码与代码文件本身的编码一致。 

如:s='中文'

如果是在utf8的文件中,该字符串就是utf8编码,如果是在gb2312的文件中,则其编码为gb2312。这种情况下,要进行编码转换,都需要先用decode方法将其转换成unicode编码,再使用encode方法将其转换成其他编码。通常,在没有指定特定的编码方式时,都是使用的系统默认编码创建的代码文件。

如果字符串是这样定义:s=u'中文'

则该字符串的编码就被指定为unicode了,即python的内部编码,而与代码文件本身的编码无关。因此,对于这种情况做编码转换,只需要直接使用encode方法将其转换成指定编码即可。

如果一个字符串已经是unicode了,再进行解码则将出错,因此通常要对其编码方式是否为unicode进行判断:

isinstance(s, unicode)  #用来判断是否为unicode

用非unicode编码形式的str来encode会报错


如何获得系统的默认编码?

#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()

该段程序在英文WindowsXP上输出为:ascii

我的win7上也输出ascii。

在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。 (我曾经遇到过一个很无语的问题,就是c++程序控制台输出总是乱码,到别人机子上就显示正常了,原来是我的cmd

设置为美国ascii模式,而不是中文GBK。

如在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编码的字符串的结果。

unicode(str,'gb2312')与str.decode('gb2312')是一样的,都是将gb2312编码的str转为unicode编码

使用str.__class__可以查看str的编码形式

原理说了半天,最后来个包治百病的吧:)

#!/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')

转自:http://www.jb51.net/article/17560.htm

----------华丽的分割线-----------------------------------------------------------------------------------------------------------

Python、Unicode和中文(转)

python的中文问题一直是困扰新手的头疼问题,这篇文章将给你详细地讲解一下这方面的知识。当然,几乎可以确定的是,在将来的版本中,python会彻底解决此问题,不用我们这么麻烦了。

先来看看python的版本:
>>> import sys
>>> sys.version
'2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]'

(一)
用记事本创建一个文件ChineseTest.py,默认ANSI:
s = "中文"
print s

测试一下瞧瞧:
E:\Project\Python\Test>python ChineseTest.py
  File "ChineseTest.py", line 1
SyntaxError: Non-ASCII character '\xd6' in file ChineseTest.py on line 1, but no encoding declared; see http://www.pytho
n.org/peps/pep-0263.html for details

(注意,上面的这段脚本在python IDLE下面没有文件,IDLE默认创建的文件都是UTF-8的。输出也没用问题,不会乱码)

偷偷地把文件编码改成UTF-8:
E:\Project\Python\Test>python ChineseTest.py
  File "ChineseTest.py", line 1
SyntaxError: Non-ASCII character '\xe4' in file ChineseTest.py on line 1, but no encoding declared; see http://www.pytho
n.org/peps/pep-0263.html for details

无济于事。。。
既然它提供了网址,那就看看吧。简单地浏览一下,终于知道如果文件里有非ASCII字符,需要在第一行或第二行指定编码声明。把ChineseTest.py文件的编码重新改为ANSI,并加上编码声明:
# coding=gbk
s = "中文"
print s

再试一下:
E:\Project\Python\Test>python ChineseTest.py
中文

正常咯:)
(二)
看一看它的长度:
# coding=gbk
s = "中文"
print len(s)
结果:4。
s这里是str类型,所以计算的时候一个中文相当于两个英文字符,因此长度为4。
我们这样写:
# coding=gbk
s = "中文"
s1 = u"中文"
s2 = unicode(s, "gbk") #省略参数将用python默认的ASCII来解码
s3 = s.decode("gbk") #把str转换成unicode是decode,unicode函数作用与之相同
print len(s1)
print len(s2)
print len(s3)
结果:
2
2
2
(三)
接着来看看文件的处理:
建立一个文件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 <module>
    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中文

(四)一点遗留问题
在第二部分中,我们用unicode函数和decode方法把str转换成unicode。为什么这两个函数的参数用"gbk"呢?
第一反应是我们的编码声明里用了gbk(# coding=gbk),但真是这样?
修改一下源文件:
# coding=utf-8
s = "中文"
print unicode(s, "utf-8")
运行,报错:
Traceback (most recent call last):
  File "ChineseTest.py", line 3, in <module>
    s = unicode(s, "utf-8")
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data
显然,如果前面正常是因为两边都使用了gbk,那么这里我保持了两边utf-8一致,也应该正常,不至于报错。
更进一步的例子,如果我们这里转换仍然用gbk:
# coding=utf-8
s = "中文"
print unicode(s, "gbk")
结果:中文
翻阅了一篇英文资料,它大致讲解了python中的print原理:
When Python executes a print statement, it simply passes the output to the operating system (using fwrite() or something like it), and some other program is responsible for actually displaying that output on the screen. For example, on Windows, it might be the Windows console subsystem that displays the result. Or if you're using Windows and running Python on a Unix box somewhere else, your Windows SSH client is actually responsible for displaying the data. If you are running Python in an xterm on Unix, then xterm and your X server handle the display.

To print data reliably, you must know the encoding that this display program expects.

简单地说,python中的print直接把字符串传递给操作系统,所以你需要把str解码成与操作系统一致的格式。Windows使用CP936(几乎与gbk相同),所以这里可以使用gbk。
最后测试:
# coding=utf-8
s = "中文"
print unicode(s, "cp936")
结果:中文

如果以上的还看不明白,再来个对话看看:
[转自http://hi.baidu.com/zjw0358/blog/item/aab19652b51e00080cf3e3ed.html]

str和unicode解析
2008-08-26 16:50
未来(初学者)(41934583) 16:33:58
其次把str转成unicode不是直接构造,是用str对象的decode方法 
Django-venjiang-.Net(69583868) 16:34:03
有汉字必须用u'...'这个吗?
未来(初学者)(41934583) 16:34:18
不是 
未来(初学者)(41934583) 16:34:38
用u构造出来的是unicode类型,不用的话构造出来是str类型 
未来(初学者)(41934583) 16:35:54
str的编码是与系统环境相关的,一般就是sys.getfilesystemencoding()得到的值 
Django-venjiang-.Net(69583868) 16:36:12
嗯.明白了.
未来(初学者)(41934583) 16:36:25
unicode你可以不管它是怎么存的,就把它看做是系统能够识别其中内容的文本类型 
未来(初学者)(41934583) 16:37:11
所以从unicode转str,被看做是把一个信息文本编码为二进制字节流的过程,要用encode方法 
Python 2.X(43602410) 16:37:18
有办法判断截取出来的那部分是汉字的前半部分后半部分么? 
头太晕django(2538288) 16:37:31
我一个同事,前些天找了一本python的电子书学习.
未来(初学者)(41934583) 16:37:46
从str转unicode,看作是从二进制串出解读出有意义的信息文本,所以要用decode
我的个人总结:
为了能直接输出中文:
前面加个:
#coding=gbk
就可以了。
raw_input("中文正常")
print "中文“
都可以正常显示
若设置编码为utf-8
#coding=utf-8;就要
input=raw_input(u'中文')
print u'中文
用utf-8不想每次都加u的办法;
#coding=utf-8import sys
reload(sys)
sys.setdefaultencoding('utf-8');print '中文'
另一篇:
http://www.cnblogs.com/yangze/archive/2010/11/16/1878469.html
-----------------------------------------------------
一篇好文;

python 中文乱码问题深入分析

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

在本文中,以'哈'来解释作示例解释所有的问题,“哈”的各种编码如下: 
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)后的存储的格式。这里它仅仅是一个字节流,没有其它的含义,如果你想使这个字节流显示的内容有意义,就必须用正确的编码格式,解码显示。 
例如:

(utf-8是unicode的一种实现方式)对于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实现,具体使用如下:

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

三、Setdefaultencoding

如上图的演示代码所示:

当把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 类似的语句声明一下编码,但是这个声明到底有什么用呢?到止前为止,我觉得它的作用也就是三个:

  1. 声明源文件中将出现非ascii编码,通常也就是中文;
  2. 在高级的IDE中,IDE会将你的文件格式保存成你指定编码格式。
  3. 决定源码中类似于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)中根本不存在,所以会报上述错误。

http://happylaoyu.blog.sohu.com/111505796.html

python 编码 乱码问题相关推荐

  1. python编码问题、乱码问题

    插入中文内容到本地MySQL数据库乱码问题的解决 首先我查到一条插入数据库的sql语句,如下: title = '中文' sql = '''INSERT INTO articles(name, url ...

  2. python 乱码转码_数据库乱码问题 Python 编码问题(Unicode 的 encode、decode 相互转换 )...

    前言: 今天有个项目需要合并(A合并到B),我所做的就是数据库的合并操作,其中出现的主要问题就是乱码的问题.乱码这个问题是很常见的问题,今天整理了下自己所理解的一点见解. 案例: NAME COMPA ...

  3. PYTHON编码处理-str与Unicode的区别

    一篇关于STR和UNICODE的好文章 整理下python编码相关的内容 注意: 以下讨论为Python2.x版本, Py3k的待尝试 开始 用python处理中文时,读取文件或消息,http参数等等 ...

  4. python编码问题总结

    http://www.xprogrammer.com/1258.html 最近利用python抓取一些网上的数据,遇到了编码的问题.非常头痛,总结一下用到的解决方案. linux中vim下查看文件编码 ...

  5. python 处理python编码的基本过程

    概括.从python1.6开始就可以处理unicode字符了. 出处:http://developer.51cto.com/art/201012/241226.htm 一.几种常见的编码格式. 1.1 ...

  6. python编码和解码_Python中的编码与解码(转)

    Python中的字符编码与解码困扰了我很久了,一直没有认真整理过,这次下静下心来整理了一下我对方面知识的理解. 文章中对有些知识没有做深入的探讨,一是我自己也没有去深入的了解,例如各种编码方案的实现方 ...

  7. 调用模块里的action_初级测试人员进阶必备Python编码模块,看过的都说好

    出品 | 51Testing软件测试网 前言 ActionHelpers类在python安装路径\Lib\site-packages\appium\webdriver\extensions 下的  a ...

  8. python判断汉字个数_python判断列表里数量python中文乱码问题大总结

    在运行这样类似的代码:#!/usr/bin/env python s="中文" print s 最近经常遇到这样的问题: 问题一:SyntaxError: Non-ASCII ch ...

  9. 在Visual Studio Code 中配置Python 中文乱码问题

    在Visual Studio Code 中配置Python 中文乱码问题 方法一:直接代码修改字符集 添加前四行代码 import io import sys #改变标准输出的默认编码 sys.std ...

最新文章

  1. Open3d学习计划—高级篇 8(网格变形)
  2. 你以为的ASP.NET文件上传大小限制是你以为的吗
  3. Linux (Ubuntu)使用vi和vim方向键变成了ABCD
  4. 全卷积神经网络( FCN ):语义分割深度模型先驱
  5. node.js介绍及Win7环境安装测试(转)
  6. Uva572(DFS+联通集)
  7. LAMP LNMP性能测试
  8. html如何设置滚动动画,JavaScript 实现页面滚动动画
  9. 359B. Permutation
  10. no module named numpy_nn.functional和nn.Module
  11. Flask笔记-通过Model访问数据库
  12. 华为服务器如何开机自动启动不了,华为手机开不了机停在开机画面怎么办【详解】...
  13. zabbix的源码安装
  14. 镁客网每周硬科技领域投融资汇总(10.21-10.27),AI芯片创企Syntiant获英特尔等头部企业投资...
  15. 分配销售组织 - 分销渠道 - 工厂
  16. 电脑基础:键盘F1~F12你会用吗?天天都看到,但会用的真没几个!
  17. SAP Scripting Tracker基本使用技巧
  18. 2的次幂表示(递归求解)
  19. python 如何匹配一撇字符_使用Python正则表达式解析斜杠和撇号
  20. 管家婆软件B/S系列打印管理器报错解决

热门文章

  1. 改动实体类后,报错java.io.InvalidClassException: XXXDTO; local class incompatibl
  2. 【C语言程序设计】实验 4
  3. 《数据结构》-第四章 串、数组和广义表(习题)
  4. 【将金令】1.5金评:洗尽铅华,静待多空拉锯
  5. 程序员2019可以看的书单
  6. 森宇文化全授权代理《彩虹护卫队》亮相戛纳开启动漫全产业链布局
  7. 使用scikit-image feature计算图像特征与常见特征示例
  8. IoT物联网平台如何实现大规模设备的高效控制?
  9. IoT物联网平台如何实现设备全球分发、就近接入?
  10. 1.微信好友定时发送信息