python:麻烦的字符集问题,一不小心就中文乱码

环境:ubantu,mysql5.7,python3.6

在涉及中文,python编程时应知应会以下知识:

1.字符集常识
1.1 概念
字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、Unicode字符集等。
1.2 ASCII字符集
ASCII(American Standard Code for Information Interchange,美国信息互换标准编码)是基于罗马字母表的一套电脑编码系统。
7位编码的字符集只能支持128个字符,为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示一个字符,共256字符。
1.3 GB2312
GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集·基本集》,由原中国国家标准总局发布,1981年5月1日实施。
GB 18030的全称是GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,是我国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场上发布的软件必须符合本标准,兼容 GB2312。
1.4 Unicode字符集
Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称,是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。
1.5Unicode和UTF-8的关系
可以参考以下文档,内容基本正确: https://blog.csdn.net/TCF_JingFeng/article/details/80134600?utm_source=blogxgwz0
1.5.1unicode的诞生
首先明白计算机能识别的都是二进制010101010这种代码,但是这些010010111人是难以看懂的,于是美国人就用ASCII码制作了一张表,里面包含从a、b、c…@%$等128个字符差不多半个字节(1111,1111256 0111,1111128),为了以后扩充方便就取了一个字节,最高位是0,就这样将英文字符、字符、数字128个包含进去了,下次计算机的0101这种二进制代码就直接查这个ASCII表就知道对应的字符。
但是,美国用的字母,德国,英国。。。最重要的我们中国汉子几万个,一张表存不下啊。
于是聪明的中国人发明了GBK编码表,gbk编码规定,计算机不能在每次都只读一个字节(00000000,8位表示一个字节)那么死板了,你要先看看第一位是不是为0,要是为0 的话,就当作ASCII码来读入一个字节,不然的话就读入两个字节(汉子太多一个字节存不下,读入两个字节表示汉字就查GBK)。
那么每个国家一个表,这可就尴尬了,相互通信的时候由于解码方式不同就会导致乱码(用ASCII发邮件,计算机查ASCII表转换成对应0101010二进制,接收的人用GBK解码,将010101取查GBK肯定就查不到啊)。
于是,国际组织就发明了一套公用的表unicode编码,将所有国家,所有字符都收进去了从0一直到100多万
1.5.2utf-8的产生
虽然世界通用的表unicode是有了,但是有人就发现这有点浪费资源啊。每次让计算机读取三个字节然后参照Unicode表解码,那么像a、b…0、1、2…这些一个字节就够了的就太浪费了。
于是uft-8,utf-16,utf-32这些编码方案就出现了。utf-16是用两个字节来编码所有的字符,utf-32则选择用4个字节来编码,utf-8为了节省资源,采用变长编码,编码长度从1个字节到6个字节不等。可由于互联网大部分是1个字节(代码很多英文的),所以最后大家选择用的最多的还是utf-8。
1.6 网页编码
打开某网页,点击鼠标右键查看源代码,可以看到具体网页的字符集,比如搜狐

2.字符集和字符序的关系
参考文献:https://blog.csdn.net/fdipzone/article/details/18180325
2.1给定一系列字符并赋予对应的编码后,所有这些字符和编码对组成的集合就是字符集(Character Set)。例如ASCII码;
2.2字符序(Collation)是指在同一字符集内字符之间的比较规则;
2.3.1 确定字符序后,才能在一个字符集上定义什么是等价的字符,以及字符之间的大小关系;
2.3.2每个字符序唯一对应一种字符集,但一个字符集可以对应多种字符序,其中有一个是默认字符序(Default Collation);
2.3.3 MySQL中的字符序名称遵从命名惯例:以字符序对应的字符集名称开头;以_ci(表示大小写不敏感)、_cs(表示大小写敏感)或_bin(表示按编码值比较)结尾。例如:在字符序“utf8_general_ci”下,字符“a”和“A”是等价的。
注:在mysql5.6.10以上版本,不支持utf8_genral_cs。

3.mysql 数据库字符集
3.1系统变量
character_set_server:默认的内部操作字符集
character_set_client:客户端来源数据使用的字符集
character_set_connection:连接层字符集
character_set_results:查询结果字符集
character_set_database:当前选中数据库的默认字符集
character_set_system:系统元数据(字段名等)字符集
3.2 查看字符集
https://www.cnblogs.com/yangmingxianshen/p/7999428.html4
3.2.1查看MYSQL数据库服务器和数据库字符集:
show variables like ‘%character%’;
3.2.2查看MYSQL所支持的字符集
show charset;
3.2.3查看库的字符集
show database status from 库名 like 表名;
3.2.4查看表的字符集
show table status from 库名 like 表名;
3.2.5查看表中所有列的字符集
show full columns from 表名;
3.3设置字符集
3.3.1创建时指定字符集
创建库的时候指定字符集:
create database 库名 default character set=字符集;
创建表的时候指定字符集:
create table 表名(属性)default character set = 字符集;
3.3.2修改字符集
修改全局字符集
set character_set_database = 字符集;
修改库的字符集
alter database 库名 default character set 字符集;
修改表的字符集
alter table 表名 convert to character set 字符集;
修改字段的字符集
alter table 表名 modify 字段名 字段属性 character set 字符集;
3.4示例
mysq>create database lw_temp default character set utf8 collate utf8_general_ci;

4 MySQL中的字符集转换过程
4.1MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
4.2进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:
4.3使用每个数据字段的CHARACTER SET设定值;
• 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);
• 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;
• 若上述值不存在,则使用character_set_server设定值。
4.4将操作结果从内部操作字符集转换为character_set_results。

5 python的字符集处理
字符串在Python内部的表示是Unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符解码(decode)成unicode,再从unicode编码(encode)成另一种编码。
若网页源代码字符集为gb2312,则需decode(‘gb2312’)转换成unicode;若为utf-8,则用decode(‘utf-8’)
python3默认使用的是str类型对字符串编码,默认使用bytes操作二进制数据流,两者不能混淆。
Python3有两种表示字符序列的类型:bytes和str。前者的实例包含原始的8位值,后者的实例包含Unicode字符。
Python2也有两种表示字符序列的类型,分别叫做str和Unicode,与Python3不同的是,str实例包含原始的8位值;而unicode的实例,则包含Unicode字符。
以下是在python3.6环境下的测试:

在这里插入图片描述
6.操作系统和文档的编码
参考文献:https://blog.csdn.net/chruan/article/details/8812110

按照utf-8创始人的愿望:
端(unicode)——传输(utf-8)——端(unicode)
但是,后来,许多网站开发者在开发网页时直接使用utf-8编码
端(utf-8)——传输(utf-8)——端(utf-8)
utf-8编码影响了网站开发者,或者说,网站开发者“扩展”了utf-8编码的使用范围。但是,网站开发者仍然无法影响各类文档的开发者,所以,word文档和一些国际通用的文档仍然使用unicode编码而不使用utf-8编码。
国际文档(txt和xml)使用unicode编码是正宗做法;操作系统和浏览器都能够“理解”unicode编码。浏览器“迫于压力”才“理解”utf-8编码。但是,操作系统有时只认unicode编码。
在中文和日文操作系统里生成的(txt和xml)文件的编码虽然都是ansi,但是,在简体中文系统下,ansi 编码代表 GB2312 编码,在日文操作系统下,ansi 编码代表 JIS 编码。不同 ansi 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ansi 编码的文本中。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值