python
unicode
bytes
str
编码

首先需要说明一下,该篇文章是以python3为基础的,python2是否适合没有验证过。
由于python编码问题确实比较多,文章篇幅可能较长,请耐心看完,绝对物超所值,何况还是免费的,只求转载的时候注明出处,谢谢!

一、 简单的编码介绍

平常我们可能听说过很多编码格式,如 ASCII码,Unicode,utf-8,gbk等等。为了不让文章臃肿,所以在这不再赘述,如想了解,请跳转到这个链接。
各种字符编码介绍

但是py3里,只有 unicode编码格式 的字节串才能叫作str。
其他编码格式的统统都叫bytes,如:gbk,utf-8,gb2312…………

在py3中,Unicode编码就像是一个枢纽,例如gbk的格式要想转化成utf-8,那么必须先转化成Unicode,然后再从Unicode转化成utf-8。

 

编码格式转换.png

二、老大难的文件操作

python各种各样的扩展卡确实给我们带来了极大的方便,但是对于初学者而言,编码问题却一而再再而三的出现,尤其以文件操作最为明显(反正我是这样的)
接下来将主要介绍文件读写操作和文件编码方式检测的方法。

  • 文件读写:open还是 codecs.open?

python读写文件估计大家都用open内置函数,但是用open方法打开会有一些问题。open打开文件只能写入str类型,不管字符串是什么编码方式。例如

  1. >>> fr = open('test.txt','a') 

  2. >>> line1 = "我爱祖国" 

  3. >>> fr.write(line1) 

这样是完全可以的。但是有时候我们爬虫或者其他方式得到一些数据写入文件时会有编码不统一的问题,所以就一般都统一转换为unicode。此时写入open方式打开的文件就有问题了。例如


  1. >>> line2 = u'我爱祖国' 

  2. >>> fr.write(line2) 


  3. Traceback (most recent call last): 

  4. File "<pyshell#4>", line 1, in <module> 

  5. fr.write(line2) 

  6. UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128) 

  7. >>> 

怎么办,我们可以将上面的line2编码成str类型,但是太麻烦。我们要把得到的东西先decode为unicode再encode为str。。。
input文件(gbk, utf-8...) ----decode-----> unicode -------encode------> output文件(gbk, utf-8...)

代替这繁琐的操作就是codecs.open,例如

  1. >>> import codecs 

  2. >>> fw = codecs.open('test1.txt','a','utf-8') 

  3. >>> fw.write(line2) 

  4. >>> 

不会报错,说明写入成功。这种方法可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数 是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述 操作。相对内置的open()来说,这个方法比较不容易在编码上出现问题。

  • 还是文件读写操作

上文中介绍的codecs.open()方法虽然明显比open要方便好用很多,但是使用这个函数的前提是我们需要知道文件的编码方式,但是事实是我们大多数情况下不知道文件的编码方式,所以一下给出两种解决办法。

  • 1.最原始的方法。。。

  1. ways = ["utf-8","gbk","gb2312","ASCII","Unicode"] 

  2. for encoding in ways: 

  3. print(encoding) 

  4. try: 

  5. with codecs.open("test.csv","r",encoding=encoding) as f: 

  6. data = f.read() 

  7. print(type(data)) 

  8. break 

  9. except Exception as e: 

  10. pass 

将python中常用的编码方式用list表示,然后用for循环逐一带入检验。由于utf-8和gbk用的较多,所以建议放在list的最前面。
一旦文件操作成功,则break,跳出循环。

  • 2.比较高端的方法

可以以bytes的形式对文件进行操作,这样即使不知道文件的编码方式也同样可以进行读写操作了,但是在最后需要进行decode或者encode。
如果对decode和encode不了解,请阅读这篇文章python编码问题之"encode"&"decode"

  1. with codecs.open("test.csv","rb") as f: 

  2. data = f.read() 

  3. print(type(data)) 

  4. encodeInfo = chardet.detect(data) 

  5. print(data.decode(encodeInfo["encoding"])) 

亲测得到的结果如下图

 

4.png

解释一下上面的代码中的chardet.detect()
chardet是一个python3自带的库,用于检测文本的编码方式,他会返回一个字典,格式是{"encoding" : "xxx", "confidence" :" xxx"}但是注意它一般只能检测bytes类型的编码格式,比如

  1. import chardet  


  2. a = "你好" 

  3. print(type(a)) 

  4. chardet.detect(a) 


  5. >>> 

  6. <class 'str'> 

  7. Traceback (most recent call last): 

  8. File "E:\Code\python\Flask\csv-mysql\test.py", line 63, in <module> 

  9. chardet.detect(a) 

  10. File "C:\Python35\lib\site-packages\chardet\__init__.py", line 25, in detect 

  11. raise ValueError('Expected a bytes object, not a unicode object') 

  12. ValueError: Expected a bytes object, not a unicode object 

总结一下:
本文一方面简单介绍了python的编码情况,另一方面介绍了文件操作中会遇到了问题以及解决的办法。

提出的建议是

  • 使用codecs.open()打开文件

  • 使用bytes方式访问文件,如rb和wb

  • 使用chardet.detect()检测bytes类型文本的编码格式,然后再解码(decode)或者编码(encode)



End

python3编码问题终结者--还搞不懂你来找我的更多相关文章

  1. 面试还搞不懂redis,快看看这40道面试题(含答案和思维导图)

    Redis 面试题 1.什么是 Redis?. 2.Redis 的数据类型? 3.使用 Redis 有哪些好处? 4.Redis 相比 Memcached 有哪些优势? 5.Memcache 与 Re ...

  2. 【转】面试还搞不懂redis,快看看这40道Redis面试题(含答案和思维导图)

    ———————————————— 版权声明:本文为CSDN博主「程序员追风」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog. ...

  3. 救救孩子吧,到现在还搞不懂TCP的三次握手四次挥手

    本文在个人技术博客同步发布,详情可用力戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩...   前几天发了一个朋友圈,发现暗恋已久的女生给我点了个赞,于是我当晚辗转反侧.彻 ...

  4. 什么鬼?你还搞不懂json和字典的区别??

    现在自动化培训烂大街,是个人都能说的上几个框架,面试如果问框架相关问题,求职者只需一瓶 82 年的雪碧,会吹的让你怀疑人生!所以面试官为了更清楚的知道你是停留在表面上的花拳绣腿还是有扎实的基础,就不会 ...

  5. 2020面试还搞不懂MyBatis?快看看这27道面试题!(含答案和思维导图)

    前言 MyBatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statem ...

  6. 转发:吐血总结,彻底明白 python3 编码原理

    吐血总结,彻底明白 python3 编码原理 写的不错,转发学习一下,侵删.. 原文地址https://zhuanlan.zhihu.com/p/40834093 防止原文看不到了 这里粘贴复制一下: ...

  7. python3编码问题

    继续收集python3编码问题相关资料 资料来源  鹏程的新浪博客(转载)http://blog.sina.com.cn/s/blog_6d7cf9e50102vo90.html  这篇鹏程老师写的关 ...

  8. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

    Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...

  9. Python2 和 Python3 编码问题

    基本存储单元 位(bit, b):二进制数中的一个数位,可以是0或者1,是计算机中数据的最小单位. 字节(Byte,B):计算机中数据的基本单位,每8位组成一个字节. 1B = 8b 各种信息在计算机 ...

随机推荐

  1. Python系列之heapq内置模块

    heapq 是 python 的内置模块,源码位于 Lib/heapq.py ,该模块提供了基于堆的优先排序算法. 堆的逻辑结构就是完全二叉树,并且二叉树中父节点的值小于等于该节点的所有子节点的值.这 ...

  2. 2.JAVA垃圾回收机制

    前言 线程独享的内存区域有程序计数器,虚拟机栈,本地方法栈,这些区域不用考虑内存回收的问题,随着线程的执行结束,自然就回收了,而堆内存和方法区的回收则不一样,他们的内存分配和回收是动态的. 1.对象存 ...

  3. Windows下搭建HTTP/HTTPS服务器及测试过程

    1 安装Apache http://www.apachehaus.com/cgi-bin/download.plx 选择合适的版本下载 本次下载的是 Apache 2.4.x VC14 Apache版 ...

  4. 基于canvas的二维码邀请函生成插件

    去年是最忙碌的一年,实在没时间写博客了,看着互联网行业中一个又一个人的倒下,奉劝大家,健康要放在首位,保重身体.好了,言归正传,这是17年的第一篇博文,话说这天又是产品同学跑过来问我说:hi,lenn ...

  5. table中td的宽度不随文字变宽

    1.设置了table的宽度后,宽度仍然不固定,td的内容一多,很容易吧table撑变形.有些时候我们需要设置固定的宽度. 解决办法 table的css 加入样式  table-layout:fixed ...

  6. python书籍推荐

    python书籍推荐列表: 技巧:关于如何在windows平台上行获取目录下的文件名称.(我的python书籍的位置E:\Python\Python_book) D:\>e: E:\>cd ...

  7. 装SQL server 2008问题解决

    在控制面板把之前安装的sql service卸载干净看看,我是这样搞定的! sql server 2008 安装过程中无法更改共享功能目录 去控制面板把相关于sql server 2008的所有程序删 ...

  8. js常见算法

    1:实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number.String.Object.Array.Boolean)进行值复制. function clone(Ob ...

  9. Cocoapods在OS X Yosemite上升级时 报错的解决方法

    原始地址:http://www.cocoachina.com/ios/20141018/9958.html 今天升级了Mac OS X 10.10-Yosemite以后运行pod install遇到下 ...

  10. c#之循环效率

    很多人在保存数据时候对于使用数组.集合等?然后遍历数据的时候是for.froeach? 下面我就写一个小例子进行测试看看,话不多说,直接用数据说话. 1.构建数据分别是数组.集合构建,数据类型分别是值 ...