Python 关于 encode与decode 中文乱码问题
字符串在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
在某些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编码的字符串的结果。
unicode(str,'gb2312')与str.decode('gb2312')是一样的,都是将gb2312编码的str转为unicode编码
使用str.__class__可以查看str的编码形式
>>>>>
groups.google.com/group/python-cn/browse_thread/thread/be4e4e0d4c3272dd
-----
python是个容易出现编码问题的语言。所以,我按照我的理解写下下面这些文字。
=首先,要了解几个概念。=
*字节:计算机数据的表示。8位二进制。可以表示无符号整数:0-255。下文,用“字节流”表示“字节”组成的串。
*字符:英文字符“abc”,或者中文字符“你我他”。字符本身不知道如何在计算机中保存。下文中,会避免使用“字符串”这个词,而用“文本”来表
示“字符”组成的串。
*编码(动词):按照某种规则(这个规则称为:编码(名词))将“文本”转换为“字节流”。(在python中:unicode变成str)
*解码(动词):将“字节流”按照某种规则转换成“文本”。(在python中:str变成unicode)
**实际上,任何东西在计算机中表示,都需要编码。例如,视频要编码然后保存在文件中,播放的时候需要解码才能观看。
unicode:unicode定义了,一个“字符”和一个“数字”的对应,但是并没有规定这个“数字”在计算机中怎么保存。(就像在C中,一个整数既
可以是int,也可以是short。unicode没有规定用int还是用short来表示一个“字符”)
utf8:unicode实现。它使用unicode定义的“字符”“数字”映射,进而规定了,如何在计算机中保存这个数字。其它的utf16等都是
unicode实现。
gbk:类似utf8这样的“编码”。但是它没有使用unicode定义的“字符”“数字”映射,而是使用了另一套的映射方法。而且,它还定义了如何在
计算机中保存。
=python中的encode,decode方法=
首先,要知道encode是 unicode转换成str。decode是str转换成unicode。
下文中,u代表unicode类型的变量,s代表str类型的变量。
u.encode('...')基本上总是能成功的,只要你填写了正确的编码。就像任何文件都可以压缩成zip文件。
s.decode('...')经常是会出错的,因为str是什么“编码”取决于上下文,当你解码的时候需要确保s是用什么编码的。就像,打开zip文
件的时候,你要确保它确实是zip文件,而不仅仅是伪造了扩展名的zip文件。
u.decode(),s.encode()不建议使用,s.encode相当于s.decode().encode()首先用默认编码(一般是
ascii)转换成unicode在进行encode。
=关于#coding=utf8=
当你在py文件的第一行中,写了这句话,并确实按照这个编码保存了文本的话,那么这句话有以下几个功能。
1.使得词法分析器能正常运作,对于注释中的中文不报错了。
2.对于u"中文"这样literal string能知道两个引号中的内容是utf8编码的,然后能正确转换成unicode
3."中文"对于这样的literal string你会知道,这中间的内容是utf8编码,然后就可以正确转换成其它编码或unicode了。
没有写完,先码那么多字,以后再来补充,这里不是wiki,太麻烦了。
>>>>>
>>>>>
=Python编码和Windows控制台=
我发现,很多初学者出错的地方都在print语句,这牵涉到控制台的输出。我不了解linux,所以只说控制台的。
首先,Windows的控制台确实是unicode(utf16_le编码)的,或者更准确的说使用字符为单位输出文本的。
但是,程序的执行是可以被重定向到文件的,而文件的单位是“字节”。
所以,对于C运行时的函数printf之类的,输出必须有一个编码,把文本转换成字节。可能是为了兼容95,98,
没有使用unicode的编码,而是mbcs(不是gbk之类的)。
windows的mbcs,也就是ansi,它会在不同语言的windows中使用不同的编码,在中文的windows中就是gb系列的编码。
这造成了同一个文本,在不同语言的windows中是不兼容的。
现在我们知道了,如果你要在windows的控制台中输出文本,它的编码一定要是“mbcs”。
对于python的unicode变量,使用print输出的话,会使用sys.getfilesystemencoding()返回的编码,把它变成str。
如果是一个utf8编码str变量,那么就需要 print s.decode('utf8').encode('mbcs')
最后,对于str变量,file文件读取的内容,urllib得到的网络上的内容,都是以“字节”形式的。
它们如果确实是一段“文本”,比如你想print出来看看。那么你必须知道它们的编码。然后decode成unicode。
如何知道它们的编码:
1.事先约定。(比如这个文本文件就是你自己用utf8编码保存的)
2.协议。(python文件第一行的#coding=utf8,html中的等)
2.猜。
>>>>>
> 将“文本”转换为“字节流”。(在python中:unicode变成str)
"最后,对于str变量,file文件读取的内容,urllib得到的网络上的内容,都是以“字节”形式的。"
虽然文件或者网页是文本的,但是在保存或者传输时已经被编码成bytes了,所以用"rb"打开的file和从socket读取的流是基于字节的.
"它们如果确实是一段“文本”,比如你想print出来看看。那么你必须知道它们的编码。然后decode成unicode。"
这里的加引号的"文本",其实还是字节流(bytes),而不是真正的文本(unicode),只是说明我们知道他是可以解码成文本的.
在解码的时候,如果是基于约定的,那就可以直接从指定地方读取如BOM或者python文件的指定coding或者网页的meta,就可以正确解码,
但是现在很多文件/网页虽然指定了编码,但是文件格式实际却使用了其他的编码(比如py文件指定了coding=utf8,但是你还是可以保存成ansi--记事本的默认编码),这种情况下真实的编码就需要去猜了
解码了的文本只存在运行环境中,如果你需要打印/保存/输出给数据库/网络传递,就又需要一次编码过程,这个编码与上面的编码没有关系,只是依赖于你的选择,但是这个编码也不是可以随便选择的,因为编码后的bytes如果又需要传递给其他人/环境,那么如果你的编码也不遵循约定,又给下一个人/环境造成了困扰,于是递归之~~~~
>>>>>
> 一般人会认为Unicode(广义)统一了编码,其实不然。Unicode不是唯一的编码,而一大堆编码的统称。但是Windows下Unicode
> (狭义)一般特指UCS2,也就是UTF-16/LE
unicode作为字符集(ucs)是唯一的,编码方案(utf)才是有很多种
>>>>>
将字符与字节的概念区分开来是很重要的。Java 一直就是这样,Python也开始这么做了,Ruby 貌似还在混乱当中。
>>>>>
>>>>>
我也说两句。我对编码的研究相对比较深一些。因为工作中也经常遇到乱码,于是在05年,对编码专门做过研究,并在公司刊物上发过文章,最后形成了一个教材,每年在公司给新员工都讲一遍。于是项目中遇到乱码的问题就能很快的定位并解决了。
理论上,从一个字符到具体的编码,会经过以下几个概念。
字符集(Abstract character repertoire)
编码字符集(Coded character set)
字符编码方式(Character encoding form)
字符编码方案(Character encoding scheme )
字符集:就算一堆抽象的字符,如所有中文。字符集的定义是抽象的,与计算机无关。
编码字符集:是一个从整数集子集到字符集抽象元素的映射。即给抽象的字符编上数字。如gb2312中的定义的字符,每个字符都有个整数和它对应。一个整数只对应着一个字符。反过来,则不一定是。这里所说的映射关系,是数学意义上的映射关系。编码字符集也是与计算机无关的。unicode字符集也在这一层。
字符编码方式:这个开始与计算机有关了。编码字符集的编码点在计算机里的具体表现形式。通俗的说,意思就是怎么样才能将字符所对应的整数的放进计算机内存,或文件、或网络中。于是,不同人有不同的实现方式,所谓的万码奔腾,就是指这个。gb2312,utf-8,utf-16,utf-32等都在这一层。
字符编码方案:这个更加与计算机密切相关。具体是与操作系统密切相关。主要是解决大小字节序的问题。对于UTF-16和UTF-32
编码,Unicode都支持big-endian 和 little-endian两种编码方案。
一般来说,我们所说的编码,都在第三层完成。具体到一个软件系统中,则很复杂。
浏览器-apache-tomcat(包括tomcat内部的jsp编码、编译,文件读取)-数据库之间,只要存在数据交互,就有可能发生编码不一致,如果在读取数据时,没有正确的decode和encode,出现乱码就是家常便饭了。
Python 关于 encode与decode 中文乱码问题的更多相关文章
- 解决python语言在cmd下中文乱码的问题
解决python语言在cmd下中文乱码的问题: a = "再见!"print (a.decode('utf-8').encode('gbk')) #解决在cmd下中文乱码的问题
- Python 编码问题:出现中文乱码-- (转)
问题描述: 在写Python代码的过程中,有用到需要输出中文的地方(python2.6.5在中文注释的地方就会出错),但是运行后会出错 我的错误显示: SyntaxError: Non-ASCII c ...
- python测试报告输出 htmltestrunner 及 中文乱码的解决方式
下载HTMLTestRunner.py 第三方库 下载地址: python2:http://tungwaiyip.info/software/HTMLTestRunner.html 右键另存为下载HT ...
- Python 爬虫过程中的中文乱码问题
python+mongodb 在爬虫的过程中,抓到一个中文字段,encode和decode都无法正确显示 注:以下print均是在mongodb中截图显示的,在pythonshell中可能会有所不同 ...
- python 的 encode 、decode、字节串、字符串
一.摆个图 DJ DJ DJ Decode. J 解码 首先得知道字符串有哪些编码格式,至于为什么会有这么多的编码格式,以后再了解更新. 1.ASCII 占1个字节,只支持英文 2.GB231 ...
- python使用zipfile解压中文乱码问题
在zipfile.ZipFile中获得的filename有中日文则很大可能是乱码,这是因为 在zip标准中,对文件名的 encoding 用的不是 unicode,而可能是各种软件根据系统的默认字符集 ...
- Python之pandas读取mysql中文乱码问题
# -*- coding: utf-8 -*- # author:baoshan import pandas as pd import pymysql config = { "host&qu ...
- python编码encode和decode
计算机里面,编码方法有很多种,英文的一般用ascii,而中文有unicode,utf-8,gbk,utf-16等等. unicode是 utf-8,gbk,utf-16这些的父编码,这些子编码都能转换 ...
- 字符串的encode与decode解决乱码问题
!/usr/bin/env python coding=utf-8 s="中文" if isinstance(s, unicode): s=u"中文" prin ...
随机推荐
- c#中的as,is和强转
as和强转之间的区别: as转换类型失败时不会抛出异常:强转类型失败时会抛出异常 引入is先对变量进行检验: if (foo is int) { i = (int)foo; } logger log ...
- 36、NSTimer使用详解-开启、关闭、移除
1.要是用一个定时器,首先要定义一个定时器: @property(strong,nonatomic)NSTimer *myTimer;//定时器 2.初始化,初始化有两种方式: 第一种: + (NST ...
- Django的开始
一 浏览器相关知识 http:只有依赖一回,属于短链接,不会报错客户端的信息. 浏览器相当于一个客户端,客户端的链接 服务端:socket服务端,起服务监听客户端的请求. import socket ...
- pt-query-digest详解慢查询日志
一.简介 pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog.General log.slowlog,也可以通过SHOWPROCESSLIST或者通过tcpdu ...
- 通过html文件生成PDF文件
/// <summary> /// 获取html内容,转成PDF(注册) /// </summary> public void DownloadPDFByHTML(string ...
- vue.js实战(文摘)
---------------第1篇 基础篇 第1章 初始vue.js 第2章 数据绑定和第一个vue应用 第3章 计算属性 第4章 v-bind及class与style绑定 第5章 内置命令 第6章 ...
- hdu6365 2018 Multi-University Training Contest 6 1004 Shoot Game
http://acm.hdu.edu.cn/showproblem.php?pid=6365 细节处理 unique返回的是最后一位的后一位,因此从1开始的数组要减去(p+1) 结构体可以用unqiu ...
- ELK简单部署
系统环境: IP:192.168.0.156 ruby环境准备 yum -y install ruby-devel ruby-libs ruby-rdoc ruby-ri ruby-static ru ...
- Mybatis-Plus 实战完整学习笔记(二)------环境搭建
第二章 使用实例 1.搭建测试数据库 -- 创建库 CREATE DATABASE mp; -- 使用库 USE mp; -- 创建表 CREATE TABLE tbl_employee( ...
- VS2013利用ajax访问不了json文件——VS2013配置webconfig识别json文件
这两天用VS2013开发工具来访问json文件,老是报404文件,我根据网上来设置IIS添加MIME重启IIS和VS2013还是失败,无法访问json文件,但是奇怪的是可以访问txt文件 查询了很多方 ...