上文提到了python开发中非常重要的两处设置。

一个是编解码器的默认设置defaultencoding

  1. >>> import sys
  2. >>> sys.getdefaultencoding()
    'ascii'

另一个是声明在python文件头部的代码编码方式coding

  1. # -*- coding: utf-8 -*-

这两处设置在python的str,unicode对象的encode和decode方法中,有非常重要的作用,直接影响到结果。下面的代码按照目前的设置进行,即defaultencoding为ascii,coding为utf-8

str和unicode

str是普通字符串,使用一般需要解码成unicode。unicode是unicode 字符串,默认使用unicode方式编码,使用一般需要解码成指定的格式。

使用str()方法创建字符串。

  1. s = str('你们') #存储时按utf-8存储
  2. print repr(s) #打印结果为'\xe4\xbd\xa0\xe4\xbb\xac'

使用unicode()方法创建的是unicode字符串,也可使用u标记。创建unicode字符串时,需指定字符串编码方式,否则按defaultencoding对字符串进行编码。

  1. u1=u'你们'
  2. u2= unicode('你们')
  3. print u1 #输出正确
  4. print u2 #存储时按utf-8存储,再按ascii编码,出错
  5. #UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
  6.  
  7. u3 = unicode('你们','utf-8') #先按utf-8编码存储,再按utf-8解码
  8. print u3 #输出正确
  9. print repr(u3) #打印结果是 u'\u4f60\u4eec'
  10.  
  11. u4 = unicode('你们','gbk') #先按utf-8编码存储,再按gbk解码
  12. print u4 #打印结果是 浣犱滑
  13. print repr(u4) #打印结果是 u'\u6d63\u72b1\u6ed1' 是 浣犱滑 三个字的unicode编码

总结,任何字符串在存储是按照指定的coding进行存储,在解码时如不指定编码方式,将按照defaultencoding对字符串进行编码。

decode()和encode()

str.decode()  用于将字符串解码成指定的格式,如果不指定编码方式,将使用默认的ascii编码方式进行编码。

  1. s = str('你们')
  2. print s.decode('utf-8') #输出正确
  3. print s.decode() #出错
  4. #UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

unicode.encode() 用于将标准的unicode编码成指定的格式,如果不指定编码方式,将使用默认的 defaultencoding进行编码。

  1. u=u'你们'
  2. print u.encode('utf-8') #输出正确
  3. print u.encode('gbk') #输出乱码,编码时为utf-8,解码时为gbk
  4. print u.encode() #出错,编码时为utf-8,解码时为ascii
  5. #UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

总结,str字符串存储和unicode字符串存储时,按照coding设置编码,str.decode() 把本身解码成指定格式,unicode.encode()把本身编码成指定格式,如果不指定编解码格式,将使用defaultencoding进行编解码。如果编码解码方式不一致,将会出错或乱码。

另有str.encode() ,unicode.decode(),这两个方法没什么用。因为str是已经编码了的字符串,无需再次编码。unicode本身已经解码成unicode了,无需再次解码。但python的就是这么好玩,为了保持对称,设计了这两个方法。

官方文档如此描述:str.encode(e) is the same as unicode(str).encode(e). This is useful since code that expects Unicode strings should also work when it is passed ASCII-encoded 8-bit strings(from Guido van Rossum) .

这段话大概意思是说encode方法本来是被unicode调的,但如果不小心被作为str对象的方法调,并且这个str对象正好是ascii编码的(ascii这一段和unicode是一样的),也应该让他成功。这就是str.encode方法的一个用处。

类似地,把光用ascii组成的unicode再decode是一样的道理,因为好像几乎任何编码里ascii都没变。因此这样的操作等于没做。 这些方法没什么用,实际使用中往往会出错,比如下面两个。

str.encode() ,首先使用默认的编码方式将str进行编码,然后使用指定的方式将对象解码

  1. s.encode("utf-8") #等价于 s.decode(defaultencoding).encode("utf-8")

unicode.decode(),首先使用默认的编码方式将对象进行解码,再用指定的方式将对象编码

  1. u.decode("utf-8") #等价于 u.encode(defaultencoding).decode("utf-8")

关于requests库

requests库在写网络爬虫的时候经常用到,使用起来非常方便。

Request对象在访问服务器后会返回一个Response对象,这个对象将返回的Http响应字节码保存到content属性中。content本身是未编码的二进制数据,如果是文本文件,则自动按str的默认方式编码。

Response对象还有一个属性text,它是一个unicode字符串对象。如果不加处理直接访问,常常会发生乱码。因为Response对象会通过另一个属性encoding来将content字节码编码成unicode,而这个encoding属性居然是responses自己猜出来的。

官方文档:

text
Content of the response, in unicode.

If Response.encoding is None, encoding will be guessed using chardet.

The encoding of the response content is determined based solely on HTTP headers, following RFC 2616 to the letter. If you can take advantage of non-HTTP knowledge to make a better guess at the encoding, you should set r.encoding appropriately before accessing this property.

responses 根据http头文件获取encoding设置,大多数情况是正确的,但有时也有例外。所以要么你使用content然后重新解码,要么把encoding设置正确。

  1. # -*- coding: UTF-8 -*-
  2. import requests
  3. url = "http://xxx.xxx.xxx" #gbk格式编码的网页
  4. response = requests.get(url)
  5. response.encoding = 'gbk'
  6.  
  7. print response.content #未编码的二进制数据,如果是文本文件,则自动按str的默认方式编码,此处按ascii编码,结果显示乱码,
  8. print response.content.decode('gbk') #按“gbk”编码之后,显示正确
  9. print response.text #显示正确

(完)

python语言中的编码问题(续)的更多相关文章

  1. python语言中的编码问题

    在编程的过程当中,常常会遇到莫名其妙的乱码问题.很多人选择出了问题直接在网上找答案,把别人的例子照搬过来,这是快速解决问题的一个好办法.然而,作为一个严谨求实的开发者,如果不从源头上彻底理解乱码产生的 ...

  2. Python语言中各种进制相互转换

    目录 Python语言中各种进制相互转换 将二进制.八进制.十进制的数分别转换成十进制的方法 将十进制转换成二进制.八进制.十六进制 Python语言中各种进制相互转换 本文参考自https://ww ...

  3. Python语言中的关键字(自己做的读书笔记)

    电脑配置:联想笔记本电脑 windows8系统 Python版本:2.7.8 本文章撰写时间:2015.1.1 作者:陈东陈 阅读说明: 1.本文都是先解释,后放图片: 2.文中斜体部分要么为需要输入 ...

  4. 聊聊python 2中的编码

    为什么需要编码: 计算机可以存储和处理二进制,那么从文字到计算机可以识别的二进制之间需要对应的关系,于是便有了ASCII,ASSCII使用7位字符,由于1byte=8bit,所以最高位补一个0,使用8 ...

  5. Python 2 中的编码

    在 Python 尤其是 Python2 中,编码问题是困扰开发者尤其初学者的一大问题.什么 Unicode/UTF-8/str ,又是 decode/encode 的,搞得人头都大了.其实不然,这有 ...

  6. 了解 Python 语言中的时间处理

    python 语言对于时间的处理继承了 C语言的传统,时间值是以秒为单位的浮点数,记录的是从1970年1月1日零点到现在的秒数,这个秒数可以转换成我们日常可阅读形式的日期和时间:我们下面首先来看一下p ...

  7. python 2 和python 3 中的编码对比

    在 Python 中,不论是 Python2 还是 Python3 中,总体上说,字符都只有两大类: 通用的 Unicode 字符: (unicode 被编码后的)某种编码类型的字符,比如 UTF-8 ...

  8. day06 python 3中的编码

    #python2 和 python3 的一些区别 ''' #python2 print('aaa') print'aaa' range() xrange()生成器 raw_input() #pytho ...

  9. Python语言中的按位运算

    (转)位操作是程序设计中对位模式或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常与加 ...

随机推荐

  1. swift开发新项目总结

    新项目用swift3.0开发,现在基本一个月,来总结一下遇到的问题及解决方案   1,在确定新项目用swift后,第一个考虑的问题是用纯swift呢?还是用swift跟OC混编      考虑到新项目 ...

  2. 软件工程(C编码实践篇)学习心得

    孟繁琛 + 原创作品转载请注明出处 + <软件工程(C编码实践篇)>MOOC课程 http://mooc.study.163.com/course/USTC-1000002006 软件工程 ...

  3. [转]nopCommerce Widgets and How to Create One

    本文转自:https://dzone.com/articles/what-are-nopcommerce-widgets-and-how-to-create-one A widget is a sta ...

  4. 12个小技巧,让你高效使用Eclipse

    集成开发环境(IDE)让应用开发更加容易.它们强调语法,让你知道是否你存在编译错误,在众多的其他事情中允许你单步调试代码.像所有的IDE一 样,Eclipse也有快捷键和小工具,这些会让您感觉轻松许多 ...

  5. CentOS 7 上部署Mono 4 和Jexus 5.6

    概述 在这篇文章中我们将讨论如何在CentOS 7操作系统,安装 jexus. mono 和 配置 jexus,因此它将能够在这种环境中运行一个asp.net mvc 4 应用.这篇文章是描述如何在 ...

  6. U3D DrawCall优化手记

    在最近,使用U3D开发的游戏核心部分功能即将完成,中间由于各种历史原因,导致项目存在比较大的问题,这些问题在最后,恐怕只能通过一次彻底的重构来解决 现在的游戏跑起来会有接近130-170个左右的Dra ...

  7. Markdown是怎样接管我的各种的写作工作的

    对于一个程序猿来说,没有什么比单纯的写代码更能让人兴奋了.如果能让你像写代码一样写文档,不用再面对那些繁琐的样式,你会怎么看?它就是Markdown!即使博客园已经有不少介绍的文章了,但是我依然还是不 ...

  8. MongoDB数据实体中的ObjectId序列化成json的一个小坑

    很多时候我们都需要对实体对象进行序列化与反序列化,而ObjectId类型,只能用mongo的驱动以bson格式来序列化,但我们对外的交互,一般是json格式. 有两种解决方案: 1.自己写一个json ...

  9. 三、Redis基本操作——List

    小喵的唠叨话:前面我们介绍了Redis的string的数据结构的原理和操作.当时我们提到Redis的键值对不仅仅是字符串.而这次我们就要介绍Redis的第二个数据结构了,List(链表).由于List ...

  10. 搭建自己的Nuget服务器

    序言 你们公司有没有好多项目,有没有好多类库,你们的类库是在tfs中管理,还是svn或者github,又或者是各自为政版本类库随意使用? 那么你们使用者写类库的时候方便吗? 有没有更新下载,版本不一致 ...