Python 编码转换与中文处理
python 中的 unicode是让人很困惑、比较难以理解的问题. 这篇文章 写的比较好,utf-8是 unicode的一种实现方式,unicode、gbk、gb2312是编码字符集.
py文件中的编码
Python 默认脚本文件都是 ANSCII 编码的,当文件 中有非 ANSCII 编码范围内的字符的时候就要使用"编码指示"来修正一个 module 的定义中,如果.py文件中包含中文字符(严格的说是含有非anscii字符),则需要在第一行或第二行指定编码声明:# -*- coding=utf-8 -*- 或者 #coding=utf-8
其他的编码如:gbk、gb2312也可以;否则会出现:
SyntaxError: Non-ASCII character '\xe4' in file test.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
python中的编码与解码
先说一下python中的字符串类型,在python中有两种字符串类型,分别是 str 和 unicode,他们都是basestring的派生类;
- str类型是一个包含Characters represent (at least) 8-bit bytes的序列;
- unicode 的每个 unit 是一个 unicode obj;
在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等,使用 encode(encoding)
# -*- 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
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')会发生什么?
#coding=UTF-8
if __name__ == '__main__':
s = '中国'
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'}
在工作中,经常遇到,读取一个文件,或者是从网页获取一个问题,明明看着是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 编码转换与中文处理的更多相关文章
- Python开发【第三章】:Python编码转换
一.字符编码与转码 1.bytes和str 之前有学过关于bytes和str之间的转换,详细资料->bytes和str(第四字符串) 2.为什么要进行编码和转码 由于每个国家电脑的字符编码格式不 ...
- python 编码转换(转)
主要介绍了python的编码机制,unicode, utf-8, utf-16, GBK, GB2312,ISO-8859-1 等编码之间的转换. 常见的编码转换分为以下几种情况: 自动识别 字符串编 ...
- python 编码转换 专题
主要介绍了python的编码机制,unicode, utf-8, utf-16, GBK, GB2312,ISO-8859-1 等编码之间的转换. 常见的编码转换分为以下几种情况: 自动识别 字符串编 ...
- python编码转换
Pyton内部的字符串一般都是unicode编码或字节字符串编码:代码中字符串的默认编码与代码文件本身的编码是一致的:编码转换通常需要以unicode编码作为中间编码进行转换,即先将其他编码的字符串解 ...
- java 中文转换成Unicode编码和Unicode编码转换成中文
转自:一叶飘舟 http://blog.csdn.net/jdsjlzx/article/details/ package lia.meetlucene; import java.io.IOExcep ...
- Java实现 中文转换成Unicode编码 和 Unicode编码转换成中文
想要实现中文字符转换为Unicode编码的话主要用到的是一个这样的包,自己可以去API文档里面查看下的 java.util.Properties; 直接进入主题吧,主要是 package Test01 ...
- Python之路3【知识点】白话Python编码和文件操作
Python文件头部模板 先说个小知识点:如何在创建文件的时候自动添加文件的头部信息! 通过:file--settings 每次都通过file--setings打开设置页面太麻烦了!可以通过:View ...
- 关于Python编码问题小记
Python编码问题小记: 引子: 最近在复习redis,当我在获取redis的key的时候,redis 存储英文和汉字下面这个样子的,我知道汉字是用16进制的UTF-8编码了,然后突然很想搞清楚字符 ...
- python编码总结
关于ASCII码和Unicode码的来源 计算机只能处理数字,如果要处理文本,需要先将文本转换成数字.早期计算机采用8bit作为一个字节(byte).所以一个字节最大为255(二进制11111111= ...
随机推荐
- 帆软报表PC端实施报表心得体会
1.报表制作完成后,预览时自动显示查询内容,在控件处设置: 2.求一列数据的最小值(除去0),并对最小值字体加粗标绿,需要对对应单元格设置条件属性,并插入公式:C6 = min(greparray(C ...
- 阿里云在云栖大会发布SaaS加速器3.0版最新成果,让天下没有难做的SaaS
2019年杭州·云栖大会顺利落幕,超过6万人次观展,200余位顶尖科学家分享了前沿技术.作为“阿里云不做SaaS”,坚持“被集成”战略的落地体现,阿里云SaaS加速器在云栖大会现场发布了SaaS加速器 ...
- 基于token的验证
认证.权限和限制 身份验证是将传入请求与一组标识凭据(例如请求来自的用户或其签名的令牌)相关联的机制.然后 权限 和 限制 组件决定是否拒绝这个请求. 简单来说就是: 认证确定了你是谁 权限确定你能不 ...
- windows系统下jupyter notebook使用虚拟环境
目录 [亲测好使]windows系统下jupyter notebook使用虚拟环境 在虚拟环境中安装jupyter,并添加到jupyter kernel 参考 [未测试,但觉得比上面那方法好,因为上面 ...
- <每日一题>算法题:小球的下落距离
题目:小东和三个朋友一起在楼上抛小球,他们站在楼房的不同层,假设小东站的楼层距离地面N米,球从他手里自由落下,每次落地后反跳回上次下落高度的一半,并以此类推知道全部落到地面不跳,求4个小球一共经过了多 ...
- C++返回引用的需求
1.重载+=操作符返回*this或者某个参数的引用可以方便链式调用,比如C++流操作就是cout<< a << b << c这样的,就是靠不停返回stream的引用 ...
- StringUtils工具
ppublic class StringUtils { private StringUtils() { } /** * 文本左边补零 * * @param maxLength 文本长度 * @para ...
- nginx i.com.conf
server { listen 9090; server_name i.com; root /Users/chong/Documents/www; # Load configuration files ...
- odoo widgets.js 笔记
// 在OpenERP的Web框架内, // 通过声明一个函数来声明一个JavaScript模块[openerp.ext_picking就是这个JS模块], // 并把这个函数放在全局变量opener ...
- 【转】IOS获取屏窗高度踩坑之window.outerHeight
近日本人在直接使用window.outerHeight获取屏窗高度时 在iphone 6中出现等于0的情况,从而导致页面发生错误 后找遍代码,测试无数,终于让我逮住了这个该死兼容 window.out ...