python3编码问题终结者--还搞不懂你来找我
首先需要说明一下,该篇文章是以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。

二、老大难的文件操作
python各种各样的扩展卡确实给我们带来了极大的方便,但是对于初学者而言,编码问题却一而再再而三的出现,尤其以文件操作最为明显(反正我是这样的)
接下来将主要介绍文件读写操作和文件编码方式检测的方法。
文件读写:open还是 codecs.open?
python读写文件估计大家都用open内置函数,但是用open方法打开会有一些问题。open打开文件只能写入str类型,不管字符串是什么编码方式。例如
- >>> fr = open('test.txt','a')
- >>> line1 = "我爱祖国"
- >>> fr.write(line1)
这样是完全可以的。但是有时候我们爬虫或者其他方式得到一些数据写入文件时会有编码不统一的问题,所以就一般都统一转换为unicode。此时写入open方式打开的文件就有问题了。例如
- >>> line2 = u'我爱祖国'
- >>> fr.write(line2)
- Traceback (most recent call last):
- File "<pyshell#4>", line 1, in <module>
- fr.write(line2)
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128)
- >>>
怎么办,我们可以将上面的line2编码成str类型,但是太麻烦。我们要把得到的东西先decode为unicode再encode为str。。。
input文件(gbk, utf-8...) ----decode-----> unicode -------encode------> output文件(gbk, utf-8...)
代替这繁琐的操作就是codecs.open,例如
- >>> import codecs
- >>> fw = codecs.open('test1.txt','a','utf-8')
- >>> fw.write(line2)
- >>>
不会报错,说明写入成功。这种方法可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数 是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述 操作。相对内置的open()来说,这个方法比较不容易在编码上出现问题。
还是文件读写操作
上文中介绍的codecs.open()方法虽然明显比open要方便好用很多,但是使用这个函数的前提是我们需要知道文件的编码方式,但是事实是我们大多数情况下不知道文件的编码方式,所以一下给出两种解决办法。
1.最原始的方法。。。
- ways = ["utf-8","gbk","gb2312","ASCII","Unicode"]
- for encoding in ways:
- print(encoding)
- try:
- with codecs.open("test.csv","r",encoding=encoding) as f:
- data = f.read()
- print(type(data))
- break
- except Exception as e:
- pass
将python中常用的编码方式用list表示,然后用for循环逐一带入检验。由于utf-8和gbk用的较多,所以建议放在list的最前面。
一旦文件操作成功,则break,跳出循环。
2.比较高端的方法
可以以bytes的形式对文件进行操作,这样即使不知道文件的编码方式也同样可以进行读写操作了,但是在最后需要进行decode或者encode。
如果对decode和encode不了解,请阅读这篇文章python编码问题之"encode"&"decode"
- with codecs.open("test.csv","rb") as f:
- data = f.read()
- print(type(data))
- encodeInfo = chardet.detect(data)
- print(data.decode(encodeInfo["encoding"]))
亲测得到的结果如下图

解释一下上面的代码中的chardet.detect()
chardet是一个python3自带的库,用于检测文本的编码方式,他会返回一个字典,格式是{"encoding" : "xxx", "confidence" :" xxx"}但是注意它一般只能检测bytes类型的编码格式,比如
- import chardet
- a = "你好"
- print(type(a))
- chardet.detect(a)
- >>>
- <class 'str'>
- Traceback (most recent call last):
- File "E:\Code\python\Flask\csv-mysql\test.py", line 63, in <module>
- chardet.detect(a)
- File "C:\Python35\lib\site-packages\chardet\__init__.py", line 25, in detect
- raise ValueError('Expected a bytes object, not a unicode object')
- ValueError: Expected a bytes object, not a unicode object
总结一下:
本文一方面简单介绍了python的编码情况,另一方面介绍了文件操作中会遇到了问题以及解决的办法。
提出的建议是
使用codecs.open()打开文件 使用bytes方式访问文件,如rb和wb 使用chardet.detect()检测bytes类型文本的编码格式,然后再解码(decode)或者编码(encode)
python3编码问题终结者--还搞不懂你来找我的更多相关文章
- 面试还搞不懂redis,快看看这40道面试题(含答案和思维导图)
Redis 面试题 1.什么是 Redis?. 2.Redis 的数据类型? 3.使用 Redis 有哪些好处? 4.Redis 相比 Memcached 有哪些优势? 5.Memcache 与 Re ...
- 【转】面试还搞不懂redis,快看看这40道Redis面试题(含答案和思维导图)
———————————————— 版权声明:本文为CSDN博主「程序员追风」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog. ...
- 救救孩子吧,到现在还搞不懂TCP的三次握手四次挥手
本文在个人技术博客同步发布,详情可用力戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩... 前几天发了一个朋友圈,发现暗恋已久的女生给我点了个赞,于是我当晚辗转反侧.彻 ...
- 什么鬼?你还搞不懂json和字典的区别??
现在自动化培训烂大街,是个人都能说的上几个框架,面试如果问框架相关问题,求职者只需一瓶 82 年的雪碧,会吹的让你怀疑人生!所以面试官为了更清楚的知道你是停留在表面上的花拳绣腿还是有扎实的基础,就不会 ...
- 2020面试还搞不懂MyBatis?快看看这27道面试题!(含答案和思维导图)
前言 MyBatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statem ...
- 转发:吐血总结,彻底明白 python3 编码原理
吐血总结,彻底明白 python3 编码原理 写的不错,转发学习一下,侵删.. 原文地址https://zhuanlan.zhihu.com/p/40834093 防止原文看不到了 这里粘贴复制一下: ...
- python3编码问题
继续收集python3编码问题相关资料 资料来源 鹏程的新浪博客(转载)http://blog.sina.com.cn/s/blog_6d7cf9e50102vo90.html 这篇鹏程老师写的关 ...
- 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下
Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...
- Python2 和 Python3 编码问题
基本存储单元 位(bit, b):二进制数中的一个数位,可以是0或者1,是计算机中数据的最小单位. 字节(Byte,B):计算机中数据的基本单位,每8位组成一个字节. 1B = 8b 各种信息在计算机 ...
随机推荐
- java udp socket(双通信)
参考博客:http://blog.csdn.net/wintys/article/details/3525643/,非常感谢 实现功能:客户端发送字符串A ->服务端接收并显示在控制台 ...
- IOS任务管理之GCD使用
前言: 前天学了IOS的NSOperation基本使用,我们得知NSOperation也是基于IOS GCD(Grand Central Dispatch)实现,其实在做IOS开发中GCD已经基本上能 ...
- 支付宝App支付~关于它的一些坑
坑这个词不仅在微信平台适用,在支付宝也一样的,下面我们来看一下我在做App支付时的一些坑! APP支持流程: 网站H5下单->向支付宝生成订单->回调app的js->app调用支付宝 ...
- Spark源码分析之Spark-submit和Spark-class
有了前面spark-shell的经验,看这两个脚本就容易多啦.前面总结的Spark-shell的分析可以参考: Spark源码分析之Spark Shell(上) Spark源码分析之Spark She ...
- android学习6——canvas的save,restore作用
先看如下代码 public class SaveRestoreActivity extends Activity { @Override public void onCreate(Bundle sav ...
- Asp.net MVC4 ExtJS权限管理系统源码 C#开发框架源码
开发环境:VS2010或以上 数据库:SQL Server 2008 r2 MVC版本:Asp.net mvc 4.0 ExtJs版本:ext-4.2 功能介绍 1.多标签,js动态加载模式,全a ...
- WPF Prism框架下基于MVVM模式的命令、绑定、事件
Prism框架下的自定义路由事件和命令绑定 BaseCode XAML代码: <Button x:Class="IM.UI.CommandEx.PrismCommandEx" ...
- 同一环境下新建Standby RAC库
需求:在同一个环境下新建Standby RAC库,即和Primary RAC在相同的磁盘组. 说明:生产环境一般不建议这样配置DG,因为存储层面是相同磁盘组,灾备的实际意义不大.我这里是用作读写分离. ...
- Memcached·Redis缓存的基本操作
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...
- Flume-ng源码解析之Source组件
如果你还没看过Flume-ng源码解析系列中的启动流程.Channel组件和Sink组件,可以点击下面链接: Flume-ng源码解析之启动流程 Flume-ng源码解析之Channel组件 Flum ...