http://my.oschina.net/u/201886/blog/64692

From: http://hi.baidu.com/jackleehit/blog/item/ea93618e1051131cb31bbaac.html
python中的unicode是让人很困惑、比较难以理解的问题,本文力求彻底解决这些问题;
1.unicode、gbk、gb2312、utf-8的关系;
http://www.pythonclub.org/python-basic/encode-detail 这篇文章写的比较好,utf-8是unicode的一种实现方式,unicode、gbk、gb2312是编码字符集;
2.python中的中文编码问题;
2.1 .py文件中的编码
Python 默认脚本文件都是ANSCII编码的,当文件中有非ANSCII编码范围内的字符的时候就要使用"编码指示"来修正。一个module的定义中,如果.py文件中包含中文字符(严格的说是含有非anscii字符),则需要在第一行或第二行指定编码声明:# -*- coding=utf-8 -*-或者 #coding=utf-8

如果声明为某种编码,文件也必须是那种编码,ide不会主动转换编码。

其他的编码如:gbk、gb2312也可以;否则会出现类似:SyntaxError: Non-ASCII character '\xe4' in file ChineseTest.py on line 1, but no encoding declared; see http://www.pytho for details这样的异常信息;
2.2 python中的编码与解码

(str就可以看做c中的数组,每个元素存储一个8个bit的字节

如果文件编码是gbk

str='我abc'  #等同于str = u'我abc'.encode("gbk")

for c in str:

print '%x' %ord(c)

output:

ce d2 61 62 63

unistr = u'我abc' #等同于 unistr = '我abc'.decode("gbk")

程序会根据文件上面声明的编码将字符串转换为unicode, 也就是'我'用一个元素表示

for c in unistr:

print '%x' %ord(c)

output:

6211 61 62 63


先说一下python中的字符串类型,在python中有两种字符串类型,分别是str和unicode,他们都是basestring的派生类;str类型是一个包含Characters represent (at least) 8-bit bytes的序列;unicode的每个unit是一个unicode obj;所以:len(u'中国')的值是2;len('ab')的值也是2;
在str的文档中有这样的一句话:The string data type is also used to represent arrays of bytes, e.g., to hold data read from a file.也就是说在读取一个文件的内容,或者从网络上读取到内容时,保持的对象为str类型;如果想把一个str转换成特定编码类型,需要把str转为Unicode,然后从unicode转为特定的编码类型如:utf-8、gb2312等;
python中提供的转换函数:
unicode转为gb2312,utf-8等
# -*- coding=UTF-8 -*-
if __name__ == '__main__':
    s = u'中国'
    s_gb = s.encode('gb2312')
utf-8,GBK转换为unicode 使用函数unicode(s,encoding) 或者s.decode(encoding)
# -*- coding=UTF-8 -*-
if __name__ == '__main__':
    s = u'中国'
    #s为unicode先转为utf-8 -> unicode和utf-8不一样
    s_utf8 =  s.encode('UTF-8')
    assert(s_utf8.decode('utf-8') == s)
普通的str转为unicode
# -*- coding=UTF-8 -*-
if __name__ == '__main__':
    s = '中国'
    su = u'中国''
    #s为unicode先转为utf-8
    #因为s为所在的.py(# -*- coding=UTF-8 -*-)编码为utf-8
    s_unicode =  s.decode('UTF-8')
    assert(s_unicode == su)
    #s转为gb2312,先转为unicode再转为gb2312
    s.decode('utf-8').encode('gb2312')
    #如果直接执行s.encode('gb2312')会发生什么?
    s.encode('gb2312')

# -*- coding=UTF-8 -*-
if __name__ == '__main__':
    s = '中国'
    #如果直接执行s.encode('gb2312')会发生什么?
    s.encode('gb2312')
这里会发生一个异常:Python 会自动的先将s解码为unicode,然后再编码成gb2312。因为解码是python自动进行的,我们没有指明解码方式,python 就会使用sys.defaultencoding 指明的方式来解码。很多情况下 sys.defaultencoding是 ANSCII,如果s不是这个类型就会出错。
拿上面的情况来说,我的sys.defaultencoding是anscii,而s的编码方式和文件的编码方式一致,是utf8的,所以出错了: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
对于这种情况,我们有两种方法来改正错误:
其一是明确的指示出s的编码方式
#! /usr/bin/env python
# -*- coding: utf-8 -*-
s = '中文'
s.decode('utf-8').encode('gb2312')
其二是更改sys.defaultencoding为文件的编码方式
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys) # Python2.5 初始化后会删除sys.setdefaultencoding 这个方法,我们需要重新载入
sys.setdefaultencoding('utf-8')
str = '中文'
str.encode('gb2312')
文件编码与print函数
建立一个文件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")
结果:中文
特别推荐:
python 编码 检测
使用chardet可以很方便的实现字符串/文件的编码检测
例子如下:
>>> import urllib
>>> rawdata = urllib.urlopen('http://www.google.cn/').read()
>>> import chardet
>>> chardet.detect(rawdata)
{'confidence': 0.98999999999999999, 'encoding': 'GB2312'}
>>>
chardet 下载地址 http://chardet.feedparser.org/
特别提示:
在工作中,经常遇到,读取一个文件,或者是从网页获取一个问题,明明看着是gb2312的编码,可是当使用decode转时,总是出错,这个时候, 可以使用decode('gb18030')这个字符集来解决,如果还是有问题,这个时候,一定要注意,decode还有一个参数,比如,若要将某个String对象s从gbk内码转换为UTF-8,可以如下操作s.decode('gbk').encode('utf-8')
可是,在实际开发中,我发现,这种办法经常会出现异常:UnicodeDecodeError: ‘gbk' codec can't decode bytes in position 30664-30665: illegal multibyte sequence
这是因为遇到了非法字符——尤其是在某些用C/C++编写的程序中,全角空格往往有多种不同的实现方式,比如\xa3\xa0,或者\xa4\x57,这些字符,看起来都是全角空格,但它们并不是“合法”的全角空格(真正的全角空格是\xa1\xa1),因此在转码的过程中出现了异常。
这样的问题很让人头疼,因为只要字符串中出现了一个非法字符,整个字符串——有时候,就是整篇文章——就都无法转码。
解决办法:s.decode('gbk', ‘ignore').encode('utf-8′)
因为decode的函数原型是decode([encoding], [errors='strict']),可以用第二个参数控制错误处理的策略,默认的参数就是strict,代表遇到非法字符时抛出异常;
如果设置为ignore,则会忽略非法字符;
如果设置为replace,则会用?取代非法字符;
如果设置为xmlcharrefreplace,则使用XML的字符引用。
python文档
decode( [encoding[, errors]])
Decodes the string using the codec registered for encoding. encoding defaults to the default string encoding. errors may be given to set a different error handling scheme. The default is 'strict', meaning that encoding errors raise UnicodeError. Other possible values are 'ignore', 'replace' and any other name registered via codecs.register_error, see section 4.8.1.
详细出处参考:http://www.jb51.net/article/16104.htm
参考:
【1】http://blog.chinaunix.net/u2/68206/showart.php?id=668359
【2】http://www.pythonclub.org/python-basic/codec
【3】http://www.pythonclub.org/python-scripts/quanjiao-banjiao
【4】http://www.pythonclub.org/python-basic/chardet

Python Unicode与中文处理相关推荐

  1. Unicode(UTF-8, UTF-16)令人混淆的概念 和 python unicode转中文及转换默认编码

    Unicode(UTF-8, UTF-16)令人混淆的概念 [转载](https://www.cnblogs.com/fnlingnzb-learner/p/6163205.html) 为啥需要Uni ...

  2. python unicode转中文_Python将Unicode代码转换为中文字符的几种方法,python,unicode,编码,汉字...

    Python中有两种默认的字符串:str和unicode.在Python中一定要注意区分"Unicode字符串" 和"unicode对象"的区别.后面所有的&q ...

  3. python unicode转中文_python3中Unicode字符转中文

    python3中将Unicode字符串转成中文 用python爬虫爬取数据时,有时候会发现爬取的数据类似于 "\u3010\u6f14\u5531\u4f1a\u30112000-\u62c ...

  4. python unicode编码转换中文_python unicode转中文及转换默认编码

    一. 在爬虫抓取网页信息时常需要将类似"\u4eba\u751f\u82e6\u77ed\uff0cpy\u662f\u5cb8"转换为中文,实际上这是unicode的中文编码.可 ...

  5. Python、Unicode和中文

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

  6. python utf-8编码转换中文_python实现unicode转中文及转换默认编码的方法

    本文实例讲述了python实现unicode转中文及转换默认编码的方法.分享给大家供大家参考,具体如下: 一.在爬虫抓取网页信息时常需要将类似"\u4eba\u751f\u82e6\u77e ...

  7. python文件编码转换工具_python实现unicode转中文及转换默认编码的方法

    本文实例讲述了python实现unicode转中文及转换默认编码的方法.分享给大家供大家参考,具体如下: 一.在爬虫抓取网页信息时常需要将类似"\u4eba\u751f\u82e6\u77e ...

  8. python unicode码转换_python实现unicode转中文及转换默认编码的方法

    本文实例讲述了python实现unicode转中文及转换默认编码的方法.分享给大家供大家参考,具体如下: 一.在爬虫抓取网页信息时常需要将类似"\u4eba\u751f\u82e6\u77e ...

  9. python unicode编码转换中文_python实现unicode转中文及转换默认编码的方法

    本文实例讲述了python实现unicode转中文及转换默认编码的方法.分享给大家供大家参考,具体如下: 一.在爬虫抓取网页信息时常需要将类似"\u4eba\u751f\u82e6\u77e ...

最新文章

  1. 调整ViewState的位置,让你的asp.net页面对搜索引擎更友好
  2. Android最佳性能实践(二)——分析内存的使用情况
  3. ubuntu 安装vsftpd 530 login incorrect
  4. 工预-Typora(A)
  5. 菜鸟成长日记(四)之WMIC简单命令应用
  6. iptables简单应用
  7. chrome插件中调用ajax,Chrome扩展程序中的Ajax调用无效
  8. 原型模式 java 深浅_Java设计模式——原型模式
  9. ++操作你还在使用加锁去保证线程的安全吗?确定不了解一下CAS机制?
  10. linux下mysql5.7以上my.cnf配置文件配置
  11. Container的限制
  12. c/c++基础篇--------------------------数据类型与变量类型
  13. 图文教程使用一套键鼠控制两台电脑
  14. 物业计算机管理系统论文,小区物业管理系统设计毕业论文
  15. 【python】语句
  16. python读取EXCEL的方式
  17. CES 2019上芯片巨头们的争夺焦点:光线追踪、“永远”在线PC、汽车
  18. 计算机视觉注意力网络(一)——简介
  19. 10大关键词解读中国互联网五年间创新飞跃在哪里
  20. vulnhub bulldog

热门文章

  1. 八十六、Spring Cloud Consul:服务治理与配置中心
  2. ALBERT第一作者亲自讲解:词向量、BERT、ALBERT、XLNet全面解析
  3. CVPR 2018论文解读 | 基于域适应弱监督学习的目标检测
  4. HDU 2063 过山车 二分图匹配 匈牙利算法
  5. 上传文件页面回显_数据回显、删除以及excel导出
  6. vc++ 6.0 创建程序快捷方式的一个例子源码_漏洞复现:phpcms v9.6.0任意文件上传漏洞(CVE201814399)...
  7. 【Java报错】java.lang.ClassCastException: xxxClass cannot be cast to java.lang.Comparable 问题重现+解决
  8. c++将int转换成string_Integer与int的区别 (== 与 equal)
  9. unity随机方向的代码_ECCV 2020 目前用于车辆重识别(vehicle reID)中最大的合成车辆数据集(代码开源)...
  10. oracle获取分组后的统计信息,并只要前五条