python处理编码问题


最近参加一个可视化的比赛,在用python处理csv数据时,编码的问题真的是让人头大。干脆写一篇博客把编码的问题梳理一遍

相关文章

字符编码和字符集

python中文乱码问题

常见的编码体系

编码的定义

编码是信息从一种形式或格式转换为另一种形式的过程也称为计算机编程语言的代码简称编码。用预先规定的方法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。编码在电子计算机、电视、遥控和通讯等方面广泛使用。编码是信息从一种形式或格式转换为另一种形式的过程。解码,是编码的逆过程。

正常情况下我们无论是做网页还是处理数据的时候都会遇到编码问题的,所以有必要对编码的方式做一个详尽的理解

ASCII编码

这个本科学c语言的时候应该就接触过了

这是美国在19世纪60年代的时候为了建立英文字符和二进制的关系时制定的编码规范,它能表示128个字符,其中包括英文字符、阿拉伯数字、西文字符以及32个控制字符。它用一个字节来表示具体的字符,但它只用后7位来表示字符(2^7=128),最前面的一位统一规定为0。

拓展的ASCII码

原本的ASCII码对于英文语言的国家是够用了,但是欧洲国家的一些语言会有拼音,这时7个字节就不够用了。因此一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使 用的编码体系,可以表示最多256个符号。但这时问题也出现了:不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码 中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0—127表示的符号是一样的,不一样的只是128—255的这一段。这个问题就直接促使了Unicode编码的产生。

Unicode

正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。而Unicode就是这样一种编码:它包含了世界上所有的符号,并且每一个符号都是独一无二的。比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字“严”。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表 。很多人都说Unicode编码,但其实Unicode是一个符号集(世界上所有符号的符号集),而不是一种新的编码方式。

但是正因为Unicode包含了所有的字符,而有些国家的字符用一个字节便可以表示,而有些国家的字符要用多个字节才能表示出来。即产生了两个问题:第一,如果有两个字节的数据,那计算机怎么知道这两个字节是表示一个汉字呢?还是表示两个英文字母呢?第二,因为不同字符需要的存储长度不一样,那么如果Unicode规定用2个字节存储字符,那么英文字符存储时前面1个字节都是0,这就大大浪费了存储空间。

上面两个问题造成的结果是:1)出现了unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示unicode。2)unicode在很长一段时间内无法推广,直到互联网的出现。

utf-8

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种unicode的实现方式。其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8的编码规则很简单,只有两条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

GBK/GB2312/GB18030

GBK和GB2312都是针对简体字的编码,只是GB2312只支持六千多个汉字的编码,而GBK支持1万多个汉字编码。而GB18030是用于繁体字的编码。汉字存储时都使用两个字节来储存。

不同编码方式之间的联系

比如:在欧美,一般直接使用ASCII码就能够满足他们的要求,因为他们只有26个字母和一些其他的字符。而且编码表示的长度只占一个字节。但是,如果他们的程序要到我们国家来使用,那么我们如果不懂英语就完全不能够使用了。我们国家汉字近10万

使用Unicode字符集(该字符集和编码几乎囊括所有国家的常用字符)。而在国内,因为还可能显示其他不常见的汉字,因此就不能采用Unicode。为此,我们国家便发明了自己的字符集和编码—-GBXXX系列,供国内使用。因此,字符集和字符编码的多样性是由于不同区域的需求多样性导致的。但是在国际上,还是使用Unicode字符集和UTF-X编码方式

有一些编码存在包含关系,比如UTF-8的第一个字节的编码规则跟ASCII码完全一样。因此,对于ASCII码的编码内容使用UTF-8也能够正确解码。字符集也是一样的。因此,ASCII码编码的内容使用UTF-8解码后,使用Unicode字符集规则来解释得到的字符串跟使用ASCII字符集解释得到的完全一样。

比如:对于同一个编码
“\u33a1”. GBK的可能解释为”你“; ISO-8859-1的解释是乱码 “?”; Unicode的解释为”你“。

原因就是因为Unicode跟GBK有部分编码解码解码规则是一样的。而ISO-8859-1是外文编码,不能识别中文
,因此无法解析。

乱码

乱码的定义

乱码,指的是由于本地计算机在用文本编辑器打开源文件时,使用了不相应字符集而造成部分或所有字符无法被阅读的一系列字符。造成其结果的原因是多种多样的。

乱码出现的原因

python处理编码

一些基本概念

python中的unicode对象

python代码中,a=u’中国’, 或者a=’中国’.decode()的结果。

python中的编码转换原则

unicode是”中介”,任何编码之间转换都需要先decode()到unicode

python文件开头注释作用

“#coding:utf-8” 告诉python用什么编码去读取这个.py文件。

问题1

问题描述

python2.7读csv中文文件乱码

问题解决

方法1

python读文件里的中文成功解决了(通过手动修改所有csv的编码为utf-8)

方法2(未验证)

import codecs codecs.open(file_path, 'r', encoding="utf-8")
这个方法没尝试,估计也可以,另外这里用的codecs的open函数,因为python2.7不支持打开文件时选择编码

问题2

问题描述

python2.7写入csv文件乱码

问题解决

with codecs.open(file_path, 'w', 'utf_8_sig')
注意这里一定要是utf-8_sig而不是utf-8,然后你需要写进去的数据文件保持utf-8格式就可以了,它这个方法打开的文件会自动显示成

问题原因

excel打开csv文件,可以识别编码“GB2312”,但是不能识别“utf-8”,所以csv文件里的中文还是需要转成中文的编码格式