python unicode和string byte
python unicode 和string那
开发过程中总是会碰到string, unicode, ASCII, 中文字符等编码的问题, 每次碰到都要现搜, 很是浪费时间, 于是这次狠下心, 一定要搞清楚python 的string和Unicode到底怎么回事.
基础知识
我们都知道计算机只认0和1, 要想在计算机显示26个字母, 就要给他们一套映射规则: 计算机能认得的符号 --> 人类可读的符号. 这转换的过程就是一套编码规则.
- 字符集: 就是一套字符的集合(比如中文4000个汉字集合)
- 字符编码: 一套法则, 能够将0/1和人类的语言之间进行转换的法则
最初字符集比较少, ASCII 码就够用了(一些控制符和26个字母), 随着计算机的发展, 各国语言都有自己独特的编码, 汉字的编码也不断地扩展, 从GBK到 GB18030/DBCS. 这个时候Unicode应运而生.
Unicode就是为了统一各国各地区的编码规则, 重新搞了一套包罗地球上所有文化, 符号的字符集! Unicode没有编码规则, 只是一套包含全世界符号的字符集. Unicode也不完美, 于是后续有了众多UTF编码(UTF-8, UTF-16).
总之搞清楚一件事情, 一个字符用了UTF-8编码的, 就要用UTF-8去解码, 不然就会出现乱码.
文本处理
在python-2.x, 处理文本时, 有string和unicode两种类型
- str类型就是一串bytes, 这种类型跟C语言中处理string是非常相似的
- unicode就是一串unicode的数字映射(code point), 用于映射某个字符与一个unicode的对应关系.
看看代码出来是如何的:
>>> a = "简书"
>>> type(a)
<type 'str'>
>>> a
'\xe7\xae\x80\xe4\xb9\xa6'
>>> print a
简书
>>> u = u"简书"
>>> type(u)
<type 'unicode'>
>>> u
u'\u7b80\u4e66'
>>> print u
简书
从上面的代码可以看到, a = "简书"
是string类型, 可以看到a是一串 '\xe7\xae\x80\xe4\xb9\xa6'
byte字符, 而u = u"简书"
是一串\uxxxx
的unicode数字, 通过print a
和 print u
可以显示出中文字符.
常见问题#1
大家经常犯的一个错误就是混淆了unicode以及通过unicode编码存储在string里面的类型.
比如上面的例子中 u'\u7b80'
是unicode, '\xe7\xae\x80'
是byte string, byte和unicode之间一一对应, 可以相互转换, 转换规则如下:
>>> '\xe7\xae\x80'.decode('utf-8')
u'\u7b80'
>>> print '\xe7\xae\x80'.decode('utf-8')
简
>>> u'\u7b80'.encode('utf-8')
'\xe7\xae\x80'
>>> print u'\u7b80'.encode('utf-8')
简
总结一下, 上面例子中
- unicode和byte都指
简
- byte string 里面存储的是unicode通过utf-8编码后得到的bytes
- 所以byte string解码(decode)后即可得到unicode
- unicode是byte string通过utf-8解码后得到的
- unicode用utf-8编码(encode)可以得到对应的bytes
Note:
总而言之 Unicode ------编码------> byte string
Unicode <-----解码------- byte string
Unicode就像是加密传输中的明文, 可以用UTF-8, UTF-16, UTF-7, UTF-32等对unicode进行加密, 最后解密还是要用回原本的加密方式来解密, 不然就解出乱码啦.
常见问题#2
对unicode或者byte string编码解码方向搞错
>>> u'\u7b80'.decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/serena/Documents/data-pipeline/data-ci-sqlbuffet-env/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u7b80' in position 0: ordinal not in range(128)
>>> '\xe7\xae\x80'.encode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128)
unicode应该是进行编码的, 如果进行decode, 是会出现UnicodeEncodeError
异常的. bytes string同理, 应该进行解码, 如果硬要进行编码的话, 则抛出UnicodeDecodeError
常见问题#3
API调用不一致的问题. 在调用别人的API的时候, 需要看清楚是传unicode还是byte string作为参数. 因为第三方的API有的是支持unicode, 有的是byte string, 甚至有的两种类型都支持. 这个时候要清楚自己传进去的参数是什么, 比如一些变量值是从http requests里面拉过来的, 这个时候你获得的变量值很有可能是unicode类型(python requests get/post把返回值都转成了unicode), 而如果第三方的API需要byte string, name就需要自己判断一下并进行转换. 否则就会出现各种奇怪的UnicodeError
虽然python 社区规定了在所有的API中使用unicode, 但是少数一部分的API处于安全考虑还是要求使用byte string. 需要注意一下.
常见问题#4
输出类型不一致.
既然python社区推动到处使用unicode, 那么我们只要在开发过程中全部都转成unicode是不是就万事大吉了? 并不是, 当你要输出文本到terminal或者到文件, 这个文本必须是byte string类型的.
如果不是的话, python会隐式地帮你将unicode转成string, python默认采用ascii编码,而中文编码不在ascii编码能够表示的范围之内,所以string无法将“你好”作为ascii编码保存为str类型。
>>> string = unicode('你好', 'utf8')
>>> print string
你好
>>> log = open('/var/tmp/debug.log', 'w')
>>> log.write(string)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
所以当你需要输出的时候, 需要将你的unicode转换成byte string再写文件, 如果有中文的话, 要用'utf-8'或'GBK'等支持中文的编码.
>>> string.encode('utf-8')
python 2.x的unicode & str其实搞清楚之后来来回回就是那些小问题, 希望对大家有帮助.
python unicode和string byte的更多相关文章
- Python Unicode与中文处理(转)
Python Unicode与中文处理 python中的unicode是让人很困惑.比较难以理解的问题,本文力求彻底解决这些问题: 1.unicode.gbk.gb2312.utf-8的关系: htt ...
- python数据类型之String(字符串)
String(字符串) 1.概述 字符串是以单引号或双引号括起来的任意文本,比如"abc",'xy'等等,请注意''或者""本身只是一种表示方式,并不是字符 ...
- 用java String类的getBytes(String charsetName)和String(byte[] bytes, String charsetName)解决乱码问题
Java中String的数据是如何存储的,查看源代码就可以知道,String的数据是存储在char[] value这样一个成员变量中的,char类型的大小在java中是2个字节 我们还知道,现在普遍使 ...
- Python学习-str与byte类型以及编码
Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str和b ...
- 关于java String类的getBytes(String charsetName)和String(byte[] bytes, String charsetName)
public byte[] getBytes(Charset charset) Encodes this String into a sequence of bytes using the given ...
- TypeError: coercing to Unicode: need string or buffer, ChatRoom found
在用django框架中遇到一个错误,是模型编写中出的错误 TypeError: coercing to Unicode: need string or buffer, ChatRoom found 解 ...
- new String(byte[])和byte[]toString() 的区别
byte[]字节数组的toString()获得的字符串和使用new String(byte[])构造一个新的字符串,这两个字符串是不一样的.Java对象都继承于Object,Object中提供了toS ...
- byte[]->new String(byte[]) -> getByte()引发的不一致问题
今天接短信接口,短信接口提供了sdk,我们可以直接用sdk发送请求然后发送对应短信. 但是想使用我们平台自定义的httpUtil实现. 然而忙了1天半,才解决这个问题,还是我同事帮忙找出问题并解决的. ...
- InputStream转换为String, byte[] data = new byte[1024]详解
/** * This file created at 2018年2月28日. * * Copyright (c) 2002-2018 Bingosoft, Inc. All rights reserv ...
随机推荐
- vue全家桶(2.3)
3.4.嵌套路由 实际生活中的应用界面,通常由多层嵌套的组件组合而成.同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如: 再来看看下面这种更直观的嵌套图: 接下来我们需要实现下面这种 ...
- Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo
在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...
- Laytpl 1.2
https://jeesite.gitee.io/front/laytpl/index.html
- 集成Swagger在线调试
SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...
- Linux distributions 发布网站
Red Hat: http://www.redhat.com SuSE: https://www.suse.com Fedora: https://getfedora.org/ CentOS: htt ...
- python-多任务-进程
什么是进程? 程序是静态的,当程序运行起来就叫做进程. 进程是操作系统分配资源的基本单元. 进程.线程的区别与优缺点 1. 定义的不同: 进程是系统进行资源分配的最小单位. 线程是进程的一个实体,是C ...
- CSS中link和@import的使用区别
我们都知道在html中引入外部的CSS 有2种方式,link标签和@import,他们又什么区别呢? 1.从属关系区别@import是 CSS 提供的语法规则,只有导入样式表的作用:link是HTML ...
- SpringCloud系列之集成分布式事务Seata应用篇
目录 前言 项目版本 项目说明 Seata服务端部署 Seata客户端集成 cloud-web module-order module-cart module-goods module-wallet ...
- Report,又是一道思维题
题目: Each month Blake gets the report containing main economic indicators of the company "Blake ...
- RocketMQ延迟消息的代码实战及原理分析
RocketMQ简介 RocketMQ是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的.高可靠.万亿级容量.灵活可伸缩的消息发布与订阅服务. 它前身是MetaQ,是阿里基于Kafka ...