热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python3unicode_【分享】Python–了解bytes、str与unicode的区别|勤奋的小青蛙

Python的字符串编码很容易把人搞混,分享一篇文章,用来解释python2.x与3.x的编码。Python3有两种表示字符序列的类型:

Python的字符串编码很容易把人搞混,分享一篇文章,用来解释python 2.x 与 3.x的编码。

Python3有两种表示字符序列的类型:bytes和str。前者的实例包含原始的8位值,后者的实例包含Unicode字符。

Python2也有两种表示字符序列的类型,分别叫做str和Unicode。与Python3不同的是,str实例包含原始的8位值;而unicode的实例,则包含Unicode字符。

想了解什么是bytes和Unicode,可以参考这里:Unicode与bytes有何区别?

一般来说,Unicode 只是一个“字符集”,它给每一个处于此字符集中的字符给予了一个编号。比如“我”,是 U+6211。然后 Unicode 本身并不指定这个 U+6211 应该是什么编码什么字节序存储和传输,那么就有了编码的这一概念。常见的比如 UTF-8、UTF-16 (LE)、UTF-16 (BE) 编码等。可能这里还会涉及到使用 BOM 来指定字节序的问题。那么当编码一定,字节序一定的时候,存储结果是肯定要落实到字节(Bytes)上来的。比如“我”字,U+6211,以 UTF-8 编码(过程略),结果就是 E6 88 91 这三个字节。存储、读取或者传输的时候,见到的就是 E6 88 91。可能还会见到 BOM - EF BB BF 在最前面。

把Unicode字符表示为二进制数据(也就是原始8位值)有许多种办法。最常见的编码方式就是UTF-8。但是,Python3的str实例和Python2的unicode实例都没有和特定的二进制编码形式相关联。要想把Unicode字符转换成二进制数据,就必须使用encode方法。要想把二进制数据转换成Unicode字符,则必须使用decode方法。

编写Python程序的时候,一定要把编码和解码操作放在界面最外围来做。程序的核心部分应该使用Unicode字符类型(也就是Python3中的str、Python2中的unicode),而且不要对字符编码做任何假设。这种办法既可以令程序接受多种类型的文本编码(如Latin-1、Shift JIS和Big5),又可以保证输出的文本信息只采用一种编码形式(最好是UTF-8)。

由于字符类型有别,所以Python代码中经常会出现两种常见的使用情境:

开发者需要原始8位值,这些8位值表示以UTF-8格式(或其他编码形式)来编码的字符。

开发者需要操作没有特定编码形式的Unicode字符。

所以,我们需要编写两个辅助(helper)函数,以便在这两种情况之间转换,使得转换后的输入数据能够符合开发者的预期。

#在Python3中,我们需要编写接受str或bytes,并总是返回str的方法:

def to_str(bytes_or_str):

if isinstance(bytes_or_str, bytes):

value = bytes_or_str.decode('utf-8')

else:

value = bytes_or_str

return value # Instance of str

#另外,还需要编写接受str或bytes,并总是返回bytes的方法:

def to_bytes(bytes_or_str):

if isinstance(bytes_or_str, str):

value = bytes_or_str.encode('utf-8)

else:

value = bytes_or_str

return value # Instance of bytes

#在Python2中,需要编写接受str或unicode,并总是返回unicode的方法:

#python2

def to_unicode(unicode_or_str):

if isinstance(unicode_or_str, str):

value = unicode_or_str.decode('utf-8')

else:

value = unicode_or_str

return value # Instance of unicode

#另外,还需要编写接受str或unicode,并总是返回str的方法:

#Python2

def to_str(unicode_or_str):

if isinstance(unicode_or_str, unicode):

value = unicode_or_str.encode('utf-8')

else:

value = unicode_or_str

reutrn vlaue # Instance of str

在Python中使用原始8位值与Unicode字符时,有两个问题需要注意。第一个问题可能会出现在Python2里面。如果str只包含7位ASCII字符,那么unicode和str实例似乎就成了同一种类型。

*可以用+操作符把这种str与unicode连接起来。

*可以用等价于不等价操作符,在这种str实例与unicode实例之间进行比较。

* 在格式字符串中,可以用’%s’等形式来代表unicode实例。

这些行为意味着,在只处理7位ASCII的情境下,如果某函数接受str,那么可以给它传入unicode;如果某函数接受unicode,那么也可以给它传入str。而在Python3中,bytes与str实例则绝对不会等价,即使是空字符串也不行。所以,在传入字符序列时必须留意其类型。

第二个问题可能会出现在Python3里面。如果通过内置的open函数获取了文件句柄,那么请注意,该句柄默认会采用UTF-8编码格式来操作文件。而在Python2中,文件操作的默认编码格式则是二进制形式。这可能会导致程序出现怪的错误,对习惯了Python2的程序员来说更是如此。

例如,现在要向文件中随机写入一些二进制数据。下面这种用法在Python2中可以正常运作,但在Python3中不行。

with open('/tmp/random.bin','w') as f:

f.write(os.urandom(10))

>>>

TypeError: must be str, not bytes

发生上述异常的原因在于,Python3给open函数添加了名为encoding的新参数,而这个新参数的默认值是’utf-8’。这样在文件句柄上进行read和write操作时,系统就要求开发者必须传入包含Unicode字符的str实例,而不接受包含二进制数据的bytes实例。为了解决这个问题,我们必须用二进制写入模式(’wb’)来开启待操作的文件,而不能像原来那样,采用字符写入模式(‘w’)。按照下面这种方式来使用open函数,即可同时适配Python2与Python3:

with open('/tmp/ramdom.bin','wb') as f:

f.write(os.urandom(10))

从文件中读取数据的时候也有这种问题。解决办法与写入时相似:用’rb’模式(也就是二进制模式)打开文件,而不要用’r’模式。要点:

- 在Python3中,bytes是一种包含8位值的序列,str是一种包含Unicode字符的序列。开发者不能以>或+等操作符来混同操作bytes和str实例。

- 在Python2中,str是一种包含8位值的序列,unicode是一种包含Unicode字符的序列。如果str只含有7位ASCII字符,那么可以通过相关的操作来同时使用str和unicode。

- 在对输入的进行操作之前,使用辅助函数来保证字符序列的类型与开发者的期望相符(有的时候,开发者想操作以UTF-8格式来编码的8位值,有的时候,则想操作Unicode字符)。

- 从文件中读取二进制数据,或向其中写入二进制数据时,总应该以’rb’或’wb’等二进制模式来开启文件。

摘自《编写高质量Python代码的59个有效方法》--第三条:了解bytes、str与unicode的区别

文章的脚注信息由WordPress的wp-posturl插件自动生成

|2|left

打赏

TIM截图20170723221205.png

ico-wechat.jpg微信扫一扫,打赏作者吧~



推荐阅读
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文介绍了Python对Excel文件的读取方法,包括模块的安装和使用。通过安装xlrd、xlwt、xlutils、pyExcelerator等模块,可以实现对Excel文件的读取和处理。具体的读取方法包括打开excel文件、抓取所有sheet的名称、定位到指定的表单等。本文提供了两种定位表单的方式,并给出了相应的代码示例。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
author-avatar
尚庆湃
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有