python中文处理


一、使用中文字符
在python源码中如果使用了中文字符,运行时会有错误,解决的办法是在源码的开头部分加入字符编码的声明,下面是一个例子:
#!/usr/bin/env python
# -*- coding: cp936 -*-
Python Tutorial中指出,python的源文件可以编码ASCII以外的字符集,最好的做法是在#!行后面用一个特殊的注释行来定义字符集:
# -*- coding: encoding -*-
根据这个声明,Python会尝试将文件中的字符编码转为encoding编码,并且,它尽可能的将指定地编码直接写成Unicode文本。
注意,coding:encoding只是告诉Python文件使用了encoding格式的编码,但是编辑器可能会以自己的方式存储.py文件,因此最后文件保存的时候还需要编码中选指定的ecoding才行。
二、中文字符的存储
>>> str = u"中文"
>>> str
u'\xd6\xd0\xce\xc4'
>>> str = "中文"
>>> str
'\xd6\xd0\xce\xc4'
u"中文"只是声明unicode,实际的编码并没有变。这样子就发生变化了:
>>> str = "中文"
>>> str
'\xd6\xd0\xce\xc4'
>>> str = str.decode("gb2312")
>>> str
u'\u4e2d\u6587'
更进一步:
>>> s = '中文'
>>> s.decode('gb2312')
u'\u4e2d\u6587'
>>> len(s)
4
>>> len(s.decode('gb2312'))
2
>>> s = u'中文'
>>> len(s)
4
>>> s = '中文test'
>>> len(s)
8
>>> len(s.decode('gb2312'))
6
>>> s = '中文test,'
>>> len(s)
10
>>> len(s.decode('gb2312'))
7
可以看出,对于实际Non-ASCII编码存储的字符串,python可以正确的识别出其中的中文字符以及中文上下文中的标点符号。
前缀“u”表示“后面这个字符串“是一个Unicode字符串”,这仅仅是一个声明,并不表示这个字符串就真的是Unicode了;就好比某正太声称自己已满18岁,但实际上他的真实年龄并不确定,现在体育界年龄造假可不稀罕幺!
那么声明成u有什么作用呢?对于Python来说,只要你声明某字符串是Unicode,它就会用Unicode的一套机制对它进行处理。比方说,做字符串操作的时候会动用到内部的Unicode处理函数,保存的时候以Unicode字符(双字节)进行保存。等等。显而易见,对于一个实际上并不是Unicode的字符串,做Unicode动作的处理,是有可能会出问题的。 u前缀只适用于你的字符串常量真的是Unicode的情况
三、中文字符的IO操作
用python处理字符串很容易,但是在处理中文的时候需要注意一些问题。比如:
a = "我们是python爱好者"
print a[0]
只能输出“我”字的前半部分,要想输出整个的“我”字还需要:
b = a[0:2]
print b
才行,很不方便,并且当一段文本中同时有中英文如何处理?最好的办法就是转换为unicode。像这样:
c = unicode(a, "gb2312")
print c[0]
这个时候c的下标对应的就是每一个字符,不再是字节,并且通过len(c)就可以获得字符数!还可以很方便的转换为其他编码,比如转换为utf-8:
d = c.encode("utf-8")
四、<type ‘str’>和<type ‘unicode’>
<type ‘str’>将字符串看作是字节的序列,而<type ‘unicode’>则将其看作是字符的序列,单个字符可能占用多个字节;字节相对于字符,其在存储层次中更低一些。
str转换为unicode要decode,可以这样想,因为要把字节序列解释成字符序列,字节序列是底层的存放方式,解码(decode)成更高层的字符以便使用;同理,unicode转换为str要encode,就象信息编码(encode)后才存储一样:
s.decode(encoding) <type 'str'> to <type 'unicode'>
u.encode(encoding) <type 'unicode'> to <type 'str'>
例如:
>>> s = 'str'
>>> type(s)
<type 'str'>
>>> type(s.decode())
<type 'unicode'>
>>> s = u'str'
>>> type(s)
<type 'unicode'>
>>> type(s.encode())
<type 'str'>
处理中文数据时最好采用如下方式:
1. Decode early(尽早decode, 将文件中的内容转化成unicode再进行下一步处理)
2. Unicode everywhere (程序内部处理都用unicode)
3. Encode late (最后encode回所需的encoding, 例如把最终结果写进结果文件)
下面是一个简单的演示,用re库查询一个中文字符串并打印:
>>> p = re.compile(unicode("测试(.*)", "gb2312"))
>>> s = unicode("测试一二三", "gb2312")
>>> for i in p.findall(s):
print i.encode("gb2312")
一二三
五、跨平台处理技巧
如果一个project必须在两个平台上开发,程序应该使用同样的encoding,比如要求所有的文件都使用UTF-8,如果实在不能统一(一般是为了满足许多所谓专家学者莫名其妙的要求),可以退而求其次,用当前系统编码决定文件内的编码:
import locale
import string
import re
#根据当前系统的encoding构造需要的编码取值
lang = string.upper(locale.setlocale(locale.LC_ALL, ""))
textencoding = None 3
#检查编码的值是不是满足我们需要的情况
if re.match("UTF-8", lang) != None:
# UTF-8编码
textencoding = "utf-8"
elif re.match(r"CHINESE|CP936", lang):
# Windows下的GB编码
textencoding = "gb18030"
elif re.match(r"GB2312|GBK|GB18030", lang):
# Linux下的GB编码
textencoding = "gb18030"
else:
# 其他情况,抛个错误吧
raise UnicodeError
fd = file(filename, "r")
fulltextlist = fd.readlines()
# 把每一行转换成unicode
for each in len(fulltextlist):
fulltextlist[i] = unicode(each, textencoding)
fd.close()
# 如果要打印的话,可以用text.encode(encoding)来恢复成多字节编码
六、异常处理
编码encoding发生在Unicode字符串转换为字节序列时,而解码decoding发生在字节序列转换为Unicode字符串时(encoding always takes a Unicode string and returns a bytes sequence, and decoding always takes a bytes sequence and returns a Unicode string)。
UnicodeDecodeError
UnicodeDncodeError通常发生在将str字符串解码为特定Unicode字符串时。由于不同的编码只能映射部分str字符串到对应的Unicode字符,所以遇到一些字符时解码会失败。
UnicodeEncodeError
UnicodeEncodeError通常发生在将Unicode字符串编码为特定字节序列时。由于不同的编码只能映射部分Unicode字符到对应的str字符串,所以遇到一些字符时编码会失败。
处理python编码转换时的UnicodeDecodeError异常
python提供的unicode转换不像iconv或是mbstowcs之类的方便。如果转换一段unicode("1234中文",'ascii') 到utf8,会直接出现UnicodeDecodeError的错误。如果在你能预知字串符的编码的时候,比如你用unicode('1234中文', 'gbk') 就不会出现错误;不过很多时候,会出现CJK混合的情况,如果要做到将一段CJK文件转换成unicode可能就行不通了。好在python的codecs提供了register_error这个功能:
register_error(name, error_handler)
原理很简单,不过要先看unicode是如何处理异常的。unicode这个函数是将一段string按输入的编码转换成目标的编码,如果出现了不与输入编码相符的,会出现一个UnicodeDecodeError的异常,通常有三种处理方法:strict、replace、ignore;默认是 strict,就是直接raise UnicodeDecodeError。通过register_error,我们也可以有自己的处理方法,如果遇到与输入的编码不符的时候,我们就自己识别,比如GBK、BIG5、JP的字符。
def cjk_replace(exc):
if not isinstance(exc, UnicodeDecodeError):
raise TypeError("don't know how to handle %r" % exc)
if exc.end + 1 > len(exc.object):
raise TypeError('unknown codec ,the object too short!')
ch1 = ord(exc.object[exc.start:exc.end])
newpos = exc.end + 1
ch2 = ord(exc.object[exc.start + 1:newpos])
sk = exc.object[exc.start:newpos]
if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK
return (unicode(sk,'cp936'), newpos)
if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5
return (unicode(sk,'big5'), newpos)
raise TypeError('unknown codec !')
codecs.register_error("cjk_replace", cjk_replace)
我们的cjk_replace现在只能处理GBK与BIG5的,因为我对编码也不是特别了解,只是大概知道GBK与BIG5的,不太了解JP的。在 cjk_replace这个函数里,我们对不认识的文字进行手工识别,如果认识的编码,就用正确的方法,并返回编码后的内容与新的pos,比如“1234中文”,在pos为4的时候,会调用我们的cjk_replace,我们会返回一个从gbk转换成utf8的“中”字,并返回下个正确的位置“文”的起始位置。当然了,处理“文”的时候,还会再调用一次。下面看看是如何使用的:
filedata = open('test.txt','r).read() #gbk and big5 file
data = unicode(filedata,'ascii','cjk_replace').encode('utf8')
小结
一个比较一般的Python中文处理的流程:
* 将欲处理的字符串用unicode函数以正确的编码转换为Unicode
* 在程序中统一用Unicode字符串进行操作
* 输出时,使用encode方法,将Unicode再转换为所需的编码
有几点要说明一下:
* 所谓“正确的”编码,指得是指定编码和字符串本身的编码必须一致。这个其实并不那么容易判断,一般来说,我们直接输入的简体中文字符,有两种可能的编码:GB2312(GBK、GB18030)、以及UTF-8
* encode成本地编码的时候,必须要保证目标编码中存在欲转换字符的内码。encode这种操作一般是通过一个本地编码对应Unicode的编码转换表来进行的,事实上每个本地编码只能映射到Unicode的一部分。但是映射的区域是不同的,比如Big-5对应的Unicode的编码范围和 GBK对应的就不一样(实际上这两个编码有部分范围是重叠的)。所以,Unicode的一些字符(比如本身就是从GB2312转换来的那些),可以映射到 GBK,但未必可以映射到Big-5,如果你想转换到Big-5,很有可能就会出现编码找不到的异常。但UTF-8的码表范围实际上和Unicode是一样的(只是编码形式不同而已),所以,理论上来说,任何本地编码的字符,都可以被转换到UTF-8
* GB2312、GBK、GB18030本质上是同一种编码标准。只是在前者的基础上扩充了字符数量
* UTF-8和GB编码不兼容
* 出现编解码异常时可能需要自己编写编解码解析函数,这需要了解一些字符编码的知识
参考资料
1、 http://bbs3.chinaunix.net/thread-1389703-1-2.html
2、 Python的中文处理及其它
http://www.go4pro.org/?p=38
3、 Python处理中文的时候的一些小技巧
http://cocre.com/?p=461
4、 Unicode In Python, Completely Demystified. Kumar McMillan
http://farmdev.com/talks/unicode
5、 python中文处理好方法
http://www.okpython.com/bbs/viewthread.php?tid=311
6、 Python的中文处理
http://hi.baidu.com/mrsz/blog/item/7812a5018c2cf2031d9583d2.html
7、 UnicodeDecodeError
http://wiki.python.org/moin/UnicodeDecodeError
8、 UnicodeEncodeError
http://wiki.python.org/moin/UnicodeEncodeError
9、 如何处理python编码转换时的UnicodeDecodeError异常
http://blog.chinaunix.net/u/8873/showart_1009737.html
10、codecs — Codec registry and base classes
http://docs.python.org/library/codecs.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352290.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号量使用例子_用信号量锁定:一个例子

信号量使用例子并发是带来有趣挑战的一个方面。 如果处理不当&#xff0c;会带来种族问题&#xff0c;这会使人们感到困惑&#xff0c;因为这些问题有时会突然出现&#xff0c;并且有时会正常工作。 当处理访问公共资源的并发线程时&#xff0c;Java语言提供了许多处理竞争条件…

.net Reactor之exe、dll文件混淆

.net Reactor之exe、dll文件混淆 .net Reactor的主要功能&#xff1a; 1.是对dll文件、exe文件进行反编译混淆 2.对dll进行内部加锁&#xff0c;限制其使用的固定机器、固定时间、部署次数 2.创建证书文件&#xff0c;用证书管理其限制的机器、时间、部署次数 页面&#xff1a;…

简述SAS逻辑库的概念及建立方法。什么是临时库和永久库?

libname student e:\mysas;SAS中利用libname命令建立逻辑库&#xff0c;虽然之后建立的与其关联的永久数据集还保存在该逻辑库所指的目录中&#xff0c;但重启SAS后该库却没有显示于库目录中。 例如e:\mysas目录已存在&#xff0c;程序data student.aaa;……重启SAS后虽然数据集…

35 岁 学python 必要_程序员:Python学不学?完全没必要纠结

随着云计算、大数据、人工智能的大量应用&#xff0c;Python这毛头小子&#xff0c;成了当红炸子鸡&#xff0c;香飘四溢&#xff0c;撒播到互联网的每个角落里。1几家欢喜几家愁&#xff0c;欢喜的人&#xff0c;早就用上了&#xff0c;国外的Twitter、Google、Yahoo&#xff…

了解连接池

1.简介 连接池是一种通过在池中打开和管理N个数据库连接来提高应用程序性能的技术。 该应用程序只是请求连接&#xff0c;使用它&#xff0c;然后将其放回池中。 当应用程序需要连接时&#xff0c;就绪连接将保持可用状态&#xff0c;以供池中使用。 池管理连接生命周期&#x…

linux上很方便的上传下载文件工具rz和sz

linux上很方便的上传下载文件工具rz和sz(本文适合linux入门的朋友) ######################################################### #《老男孩linux就业培训中心-初级班第七期第一节内容总结。 #linux上很方便的上传下载文件工具rz和sz #date:2011-06-15 #作者&#xff1a;老男孩…

SAS学习︱逻辑库、数据集创建与查看、数据库链接(SAS与R的code对照)

一、逻辑库、数据集、数据字典 数据字典>逻辑库>数据集 逻辑库工作空间&#xff0c;存储四类内容&#xff0c;test是数据集文件&#xff0c;views是视图&#xff08;相当于R里面的views点击查看&#xff09;&#xff0c;formats代表文件&#xff0c;sasmacr代表目录内容…

sqlserver 如何把一列分为一行显示_SqlServer数据库如何快速修改表的一列值

工作中我们会遇到一个表的一列值需要进行整体更换为另一个表的某个字段的值&#xff0c;那么我们该如何处理呢&#xff1f;数据源Room表新的Room表现将Room表的RoomTypeID列替换成Room_new表的RoomTypeID方法一&#xff1a;直接修改update Room set RoomTypeID (select RoomTy…

Linux 命令行通配符及转义符的实现

我们想对一类文件批量操作&#xff0c;例如批量查看硬盘文件属性&#xff0c;那么正常命令会是&#xff1a; [rootlinuxprobe ~]# ls /dev/sda [rootlinuxprobe ~]# ls /dev/sda1 [rootlinuxprobe ~]# ls /dev/sda2 [rootlinuxprobe ~]# ls /dev/sda3 但有些时候确实不知道分区…

windows python 访问mtp存储空间_用Windows电脑训练深度学习模型?超详细配置教程来了...

虽然大多数深度学习模型都是在 Linux 系统上训练的&#xff0c;但 Windows 也是一个非常重要的系统&#xff0c;也可能是很多机器学习初学者更为熟悉的系统。要在 Windows 上开发模型&#xff0c;首先当然是配置开发环境。Kaggle Master 及机器学习实践者 Abhinand 立足于自己的…

Matlab自带排序函数sort用法

Matlab自带排序函数sort用法 [Y,I] sort(X,DIM,MODE) sort函数默认Mode为ascend为升序&#xff0c;sort(X,descend)为降序排列。 sort(X)若X是矩阵&#xff0c;默认对X的各列进行升序排列 sort(X,dim) dim1时等效sort(X) dim2时表示对X中的各行元素升序排列 Matlab中给一维向量…

PostgreSQL学习手册(数据表)

一、表的定义&#xff1a; 对于任何一种关系型数据库而言&#xff0c;表都是数据存储的最核心、最基础的对象单元。现在就让我们从这里起步吧。 1. 创建表&#xff1a; CREATE TABLE products ( product_no integer, name text, price nu…

织梦联动类别-地区调用不显示第三级城市的解决方法

织梦联动类别-地区调用不显示第三级城市的原因 1、附加表dede_addoninfos 或者 你的其他表中的字段nativeplace数据类型为int型&#xff0c;无法保存第三级城市对应的的evalue值(比如&#xff1a;东山区 对应的 10001.001) 2、枚举表dede_sys_enum中的第三级城市对应evalue值…

js 随机1-10随机数_寻找随机的错误-一个真实的故事

js 随机1-10随机数几周前&#xff0c;我完成了RapidFTR开源项目的错误查找 &#xff0c;这花了我三个晚上。 我认为可能值得分享狩猎的故事。 本文将介绍我的工作。 我将概述我的旅程&#xff0c;以便真正找到正在发生的事情的根本原因。 我在本文中的目标是突出显示可以使用的…

用python写九九乘法口诀表左上角_python打出九九乘法口诀表

用IDLE打出乘法口诀表&#xff0c;想要就是如下图的结果&#xff1a;实现算法很简单&#xff0c;但是IDLE(python3.7)默认的换行输出方式不太容易实现&#xff0c;得需费一番脑筋。代码如下&#xff1a;*row0 #设置行数&#xff0c;值为1时候…

设计模式(一)Chain Of Responsibility责任链模式

设计模式篇章&#xff0c;源于网课的学习&#xff0c;以及个人的整理 在我们接收用户提交的字符时&#xff0c;常常会使用到过滤&#xff0c;在学习责任链模式前&#xff0c;我们是这样做的 1.定义一个类 public class MsgProcesser {String msg;public MsgProcesser(String ms…

如果你是IT技术人员,请思考这15个问题

行内的人自嘲是程序猿、屌丝和码农&#xff0c;行外的人也经常拿IT人调侃&#xff0c;那么究竟是IT人没有价值&#xff0c;还是没有仔细思考过自身的价值&#xff1f; 1.搞IT的是屌丝、码农、程序猿&#xff1f; 人们提到IT人的时候&#xff0c;总会想到他们呆板、不解风情&…

在Windows上运行-XX:CompileCommand

HotSpot JVM提供了几个与即时 &#xff08; JIT &#xff09;编译有关的命令行参数。 在本文中&#xff0c;我介绍了开始应用命令行标志-XX&#xff1a;CompileCommand所需的步骤&#xff0c;以查看对单个方法执行的即时编译。 JIT概述 Nikita Salnikov-Tarnovski的博客文章您…

匹配中文字符的正则表达式: [u4e00-u9fa5](

匹配双字节字符(包括汉字在内)&#xff1a;[^x00-xff]评注&#xff1a;可以用来计算字符串的长度&#xff08;一个双字节字符长度计2&#xff0c;ASCII字符计1&#xff09;匹配空白行的正则表达式&#xff1a;ns*r评注&#xff1a;可以用来删除空白行匹配HTML标记的正则表达式&…

python define function的顺序_Python怎么根据一个函数来决定列表顺序

def__init__(self,function):self._queue[]self.functionfunction然后要写一往列表里增加元素的方法&#xff0c;按照function排序&#xff0c;function类型为函数defadd(self,item):"""AddtothisP...def __init__(self,function):self._queue []self.function…