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 ...
随机推荐
- 关于Maven我应该知道的事
https://www.cnblogs.com/best/p/9676515.html bilibili 这里不是入门指南, 而是一些个人使用遇到的问题参考 一.环境 Maven 版本JDK要求 Ma ...
- asp.net Core依赖注入(自带的IOC容器)
今天我们主要讲讲如何使用自带IOC容器,虽然自带的功能不是那么强大,但是胜在轻量级..而且..不用引用别的库. 在新的ASP.NET Core中,大量的采用了依赖注入的方式来编写代码. 比如,在我们的 ...
- SELinux已经允许,为什么日志显示的仍然是denied?
从日志可以看到,SELinux的Mode已经修改位了permissive = 1,也就是允许模式,但它前面的日志仍然显示的是“denied".本来我还以为是自己哪里没弄好导致的这个问题,但访 ...
- Oracle Online Patching报错"This is not a RAC setup. OPatch cannot determine the local node name"
Oracle Online Patching报错"This is not a RAC setup. OPatch cannot determine the local node name&q ...
- 通过注入DLL后使用热补丁钩取API
通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...
- drf路由与认证
目录 一.路由 1 没有继承视图集的视图类 2 继承了视图集的视图类 3 继承自ModelViewSet的路由写法(自动生成) 二.认证 1 drf认证的源码分析 2 自定义认证类的使用 一.路由 三 ...
- Jmeter(十六) - 从入门到精通 - JMeter前置处理器(详解教程)
1.简介 前置处理器是在发出“取样器请求”之前执行一些操作.如果将前置处理器附加到取样器元件,则它将在该取样器元件运行之前执行.前置处理器最常用于在取样器请求运行前修改其设置,或更新未从响应文本中提取 ...
- 数据可视化之powerBI入门(十)认识Power BI的核心概念:度量值
https://zhuanlan.zhihu.com/p/64150720 本文学习PowerBI最重要的概念:度量值 初学Power BI一般都会对度量值比较困惑,毕竟对长期接触Excel的人来说, ...
- python 并发专题(十二):基础部分补充(四)协程
相关概念: 协程:一个线程并发的处理任务 串行:一个线程执行一个任务,执行完毕之后,执行下一个任务 并行:多个CPU执行多个任务,4个CPU执行4个任务 并发:一个CPU执行多个任务,看起来像是同时执 ...
- mysql中DDL库和表的管理
#DDL /* 数据定义语言 库和表的管理 一.库的管理 创建.修改.删除 二.表的管理 创建.修改.删除 创建:create 修改:alter 删除:drop */ #一.库的管理 #1.库的创建 ...