上半年的KPI,是用python作一个测试桩系统,如今系统框架基本也差很少定下来了。里面有用到新学的工厂设计模式以及以及经常使用的大牛写框架的业务逻辑和python小技巧。发现以前本身写的代码仍是面向过程思想的多,基本没有面向对象的思想,近半年看的代码给了很大的触动,我须要升级个人技能了,因而也花了挺多时间在这个KPI学习上,如今先总结下在作这个系统时我所面临到的python的字符编码问题。html
字符编码问题,若是处理有问题,可能直接就报错了;若是处理不得当,中文就会显示乱码。这是最初接触字符编码遇到问题最简洁的表达。通常都会遇到如下几个问题(逐渐升级的头疼问题):python
1. 使用编辑器或者Python IDE直接打印中文,报错或者乱码;mysql
2. 前台传输过来包含中文的字符串在后台打印,报错或者乱码;web
3. DB交互,从DB查询或者insert的中文,操做时报错或者乱码;sql
4. 文件操做,从文件中读取或者写文件时,报错或者乱码;数据库
除了第四个问题,暂时我没遇到过,前面3个问题,我遇到好几回了;遇到字符编码问题,若是想着就解决当前的问题,随便在百度上,狂搜各类方法乱试,可能还真能解决这个问题,可是耗时太长了,下次再遇到同样会头炸开,我以为学习解决这个问题须要通过如下几个过程:设计模式
1. 简单的了解计算机字符编码的发展史,ASCII编码是啥? EASCII是啥?GBK是啥?unicode是啥?UTF-8是啥?UTF-16是啥?若是这些最初级的基本概念不了解,后面学习会很困难。服务器
2. 理解python的字符串的数据类型,str和unicode,二者之间是如何转换的?网络
3. mysql支持哪些字符?mysql的环境变量跟字符集相关的有七,八个,都是神马意思?最简单的要怎么使用?app
第一:字符编码的前世此生
1989年,荷兰人Guido van Rossum发明python语言,第一个公开发行版发行于1991年,当时在那个时代,是不关心编码问题的并且英文字符个数自己也是有限的,26个字母,10个数字,标点符号,键盘上加起来能输入的字符就一百多个,用一个字节来存储已经够了,8个比特位能存256个字符。因而美国人制定了一套字符编码标准ASCII。最开始的ASCII只定义了128个字符,包括96个字符和32个控制符,所以 ASCII 只使用了一个字节的后7位,最高位都为0。
随着时代的进步,计算机开始普及到千家万户,计算机进入中国面临的一个问题就是字符编码,中国的汉字是人类使用频率最多的文字,常见的汉字就有成千上万,大大超出了 ASCII 编码所能表示的字符范围了,因而中国人本身弄了一套编码叫 GB2312,GB2312 编码共收录了6763个汉字,同时他还兼容 ASCII,GB 2312的出现,基本知足了汉字的计算机处理须要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率,不过 GB2312 仍是不能100%知足中国汉字的需求,对一些罕见的字和繁体字 GB2312 无法处理,后来就在GB2312的基础上建立了一种叫 GBK 的编码,GBK 不只收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。一样 GBK 也是兼容 ASCII 编码的,对于英文字符用1个字节来表示,汉字用两个字节来标识。
世界语言种类有多少,计算机的字符编码相应就会增长多少。因而统一联盟国际组织提出了Unicode编码,Unicode的学名是”Universal Multiple-Octet Coded Character Set”,简称为UCS。Unicode有两种格式:UCS-2和UCS-4。UCS-2就是用两个字节编码,一共16个比特位,这样理论上最多能够表示65536个字符,不过要表示全世界全部的字符显示65536个数字还远远不过,由于光汉字就有近10万个,所以Unicode4.0规范定义了一组附加的字符编码,UCS-4就是用4个字节(实际上只用了31位,最高位必须为0)。世界上任何一个字符均可以用一个Unicode编码来表示,一旦字符的Unicode编码肯定下来后,就不会再改变了。可是Unicode有必定的局限性,一个Unicode字符在网络上传输或者最终存储起来的时候,并不见得每一个字符都须要两个字节,好比一字符“A“,用一个字节就能够表示的字符,却使用两个字节,太浪费空间了。UTF-8(8-bit Unicode Transformation Format)就出现了,UTF-8是一种针对Unicode的可变长度字符编码,又称万国码。UTF-8用1到6个字节编码Unicode字符。
第二:python 字符串类型
python2.X 系统的默认编码是ASCII,3.X系统就是unicode,因此在2.X系列遇到的编码问题会更多。
1
2
3
4
5
|
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
|
如今会遇到第一类问题,在python源代码文件中若是不显示地指定编码的话,将出现语法错误:
这个提示很明显,非ASCII码在源代码中出现了。单纯的出现这类问题,能够采用如下方法解决:
方法一:在 文件前指定编码格式:
#!/usr/bin/env python #coding:UTF-8
方法二:设置整个系统的字符编码才能解决问题:(结合方法一一块儿使用)
default_encoding = 'utf-8'
if sys.getdefaultencoding() != default_encoding: reload(sys) sys.setdefaultencoding(default_encoding)
方法一和方法二都尝试了还有问题,可能就是你的编辑器的显示问题了,我使用的是pycharm,在file-setting里能够这样的设置:
调试IDE编码和project编码后,终于能打印中文了:
以前,刚学习python的时候,总结的一段:
1. 不设置源文件编码格式,输入中文,后直接打印,会提示存在‘non-ascii’,编译不经过
2. 设置源文件编码格式为gbk,输入中文后,打印乱码
3. 设置源文件编码格式为gbk,输入中文s1 = u'测试'后,打印正常
4. 设置源文件编码格式为gbk,输入中文后,先将字符串解码decode或者unicode方法,后打印正常
5. 设置源文件编码格式为utf-8,输入中文后直接输出正常
6. 设置工具和工程的默认编码为gbk,输入中文后,打印正常。
从python2.0开始,就有一种新的数据类型 Unicode Strings,可是在python3的到来,这个概念已经被弱化了。python2.*的默认编码格式是ASCII码,而python3.*的默认编码格式已经换成了Unicode。在python2中和字符串相关的数据类型,分别是str、unicode两种,他们都是basestring的子类,可见str与unicode是两种不一样类型的字符串对象。区分一个
变量是字符仍是unicode,可使用type方法:
>>> a='好'
>>> type(a) <type 'str'>
>>> a '\xe5\xa5\xbd'
>>> b=u'好'
>>> type(b) <type 'unicode'>
>>> b u'\u597d'
Python中str和unicode之间是如何转换的呢?这两种类型的字符串类型之间的转换就是靠这两个方法decode
和encode
。
这2个函数的具体使用,就不举例了。网上这类文章挺多的。这时就有可能遇到第二个问题,前台传入的中文在后台乱码,没法处理。通常出现这类问题,都是先后台编码格式不一致致使的;
方法一:统一先后台编码格式;
方法二:若是没法统一,那取数据的时候就须要进行转码处理,以前我遇到一个问题,前台传入的是GBK格式的中文,我是作后台处理的,后台全系统都是用utf8编码的,接收到GBK的http请求后,显示的中文是乱码的,致使解析那段GBK的xml都报异常。后面作了调整,再接收到前台的GBK字符串后,首先decode(gbk)再encode(utf8)就成功了。
第三:操做DB,须要了解的mysql字符集。
使用python对DB的操做,随时都有可能出现乱码。网上搜如下2个方法偶尔也能解决问题:
方法一:conn = MySQLdb.connect(self.host,self.username,self.password,self.database,charset='gbk')
方法二:
一、 客户端和服务器创建链接后,客户端以什么字符编码发送数据?
答:服务器以character_set_client系统变量被设置, conn = MySQLdb.connect(self.host,self.username,self.password,self.database,charset='gbk') 只是设置了客户端发生数据的字符编码格式
二、服务器在收到语句后将其翻译成什么字符集?
答:服务器使用character_set_connection和collation_connection系统变量。它将收到的字符集从character_set_client转到character_set_connection,而后再进行处理。