关于python 字符串编码一直没有搞清楚,今天总结了一下。

Python 字符串类型

Python有两种字符串类型:str 与 unicode。

字符串实例

# -*- coding: utf-8 -*-

# 这个是 str 的字符串
s = '关关雎鸠' # 这个是 unicode 的字符串
u = u'关关雎鸠' print isinstance(s, str) # True
print isinstance(u, unicode) # True print s.__class__ # <type 'str'>
print u.__class__ # <type 'unicode'>

前面的申明表明,上面的 Python 源代码由 utf-8 编码,由于代码中有中文,所以需要加上。

# -*- coding: utf-8 -*-

两种python字符串类型之间的转换

# 从 str 转换成 unicode
print s.decode('utf-8') # 关关雎鸠 # 从 unicode 转换成 str
print u.encode('utf-8') # 关关雎鸠

为什么从 unicode 转 str 是 encode,而反过来叫 decode?

因为 Python 认为 16 位的 unicode 才是字符的唯一内码,而大家常用的字符集如 gb2312,gb18030/gbk,utf-8,以及 ascii 都是字符的二进制(字节)编码形式。把字符从 unicode 转换成二进制编码,当然是要 encode。

反过来,在 Python 中出现的 str 都是用字符集编码的 ansi 字符串。Python 本身并不知道 str 的编码,需要由开发者指定正确的字符集 decode。

如果用错误的字符集来 encode/decode 会怎样?

# 用 ascii 编码含中文的 unicode 字符串
u.encode('ascii') # 错误,因为中文无法用 ascii 字符集编码
# UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128) # 用 gbk 编码含中文的 unicode 字符串
u.encode('gbk') # 正确,因为 '关关雎鸠' 可以用中文 gbk 字符集表示
# '\xb9\xd8\xb9\xd8\xf6\xc2\xf0\xaf'
# 直接 print 上面的 str 会显示乱码,修改环境变量为 zh_CN.GBK 可以看到结果是对的 # 用 ascii 解码 utf-8 字符串
s.decode('ascii') # 错误,中文 utf-8 字符无法用 ascii 解码
# UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128) # 用 gbk 解码 utf-8 字符串
s.decode('gbk') # 不出错,但是用 gbk 解码 utf-8 字符流的结果,显然只是乱码
# u'\u934f\u51b2\u53e7\u95c6\u5ea8\u7b2d'

陷阱

这要提到处理 Python 编码时容易遇到的陷阱。

字符串连接


# -*- coding: utf-8 -*-
# file: example2.py # 这个是 str 的字符串
s = '关关雎鸠' # 这个是 unicode 的字符串
u = u'关关雎鸠' s + u # 失败,UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

在进行同时包含 str 与 unicode 的运算时,Python 一律都把 str 转换成 unicode 再运算,当然,运算结果也都是 unicode。

由于 Python 事先并不知道 str 的编码,它只能使用 sys.getdefaultencoding() 编码去 decode。sys.getdefaultencoding() 的值一般是 'ascii'。

显然,如果需要转换的 str 有中文,一定会出现错误。

% 运算的结果

# 正确,所有的字符串都是 str, 不需要 decode
"中文:%s" % s # 中文:关关雎鸠 # 失败,相当于运行:"中文:%s".decode('ascii') % u
"中文:%s" % u # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128) # 正确,所有字符串都是 unicode, 不需要 decode
u"中文:%s" % u # 中文:关关雎鸠 # 失败,相当于运行:u"中文:%s" % s.decode('ascii')
u"中文:%s" % s # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

在 Python 3 已经取消了 str,让所有的字符串都是 unicode ——这也许是个正确的决定。

总结

string 模块已经停止了更新,只保留了 ASCII 码的支持,string 模块已经不推荐使用,在任何需要跟 Unicode 兼容的代码里都不要再用该模块,Python 保留该模块仅仅是为了向后兼容.

Python 把硬编码的字符串叫做字面上的字符串,默认所有字面上的字符串都用 ASCII 编码,可以通过在字符串前面加一 个'u'前缀的方式声明 Unicode 字符串,这个'u'前缀告诉 Python 后面的字符串要编码成 Unicode 字符串 .

内建的 str()函数和 chr()函数并没有升级成可以处理 Unicode.它们只能处理常规的 ASCII 编码字符串,如果一个 Unicode 字符串被作作为参数传给了 str()函数,它会首先被转换 成 ASCII 字符串然后在交给 str()函数.

如果该 Unicode 字符串中包含任何不被 ASCII 字符串支 持的字符,会导致 str()函数报异常.同样地,chr()函数只能以 0 到 255 作为参数工作.如果你 传给它一个超出此范围的值(比如说一个 Unicode 字符),它会报异常.

新的内建函数 unicode()和 unichar()可以看成 Unicode 版本的 str()和 chr().Unicode() 函数可以把任何 Python 的数据类型转换成一个 Unicode 字符串,如果是对象,并且该对象定义 了__unicode__()方法,它还可以把该对象转换成相应的 Unicode 字符串.

处理字符串的准则:

  • 程序中出现字符串时一定要加个前缀u.
  • 不要用str()函数,用unicode()代替.
  • 不要用过时的 string 模块 -- 如果传给它的是非 ASCII 字符,它会把一切搞砸。
  • 不到必须时不要在你的程序里面编解码 Unicod 字符.只在你要写入文件或数据库或者网络时,才调用 encode()函数;相应地,只在你需要把数据读回来的时候才调用 decode() 函数.

参考

http://in355hz.iteye.com/blog/1860787

《python核心编程 第二版》

python编码encode decode(解惑)的更多相关文章

  1. python编码encode和decode

    计算机里面,编码方法有很多种,英文的一般用ascii,而中文有unicode,utf-8,gbk,utf-16等等. unicode是 utf-8,gbk,utf-16这些的父编码,这些子编码都能转换 ...

  2. python编码问题 decode与encode

    参考: http://www.jb51.net/article/17560.htm 如果要在python2的py文件里面写中文,则必须要添加一行声明文件编码的注释,否则python2会默认使用ASCI ...

  3. Python编码(encode)和解码(Decode)常见的两个错误

    项目地址:https://git.io/pytips 0x07 和 0x08 分别介绍了 Python 中的字符串类型(str)和字节类型(byte),以及 Python 编码中最常见也是最顽固的两个 ...

  4. [Python函数]encode,decode

    前言: 我们知道,计算机是以二进制为单位的,也就是说计算机只识别0和1,也就是我们平时在电脑上看到的文字,只有先变成0和1,计算机才会识别它的意思.这种数据和二进制的转换规则就是编码.计算机的发展中, ...

  5. is 和 == 区别,id() ,回顾编码,encode(),decode()

    1. is 和 == 区别 id()函数 == 判断两边的值 is 判断内存地址例 s = "alex 是 大 xx"# abc = id(s) # 得到内存地址# print(a ...

  6. 字符编码和python使用encode,decode转换utf-8, gbk, gb2312

    ASCII码 标准ASCII码使用7位二进制数表示大写或小写字母,数字0到9标点符号以及在美式英语中使用的特殊控制字符. 在标准ASCII码中,最高位(b7)用作奇偶校验位,所谓奇偶校验,是指在代码传 ...

  7. Python 编码encode()、 解码decode()问题

    乱码这种东西,时不时出现.本来开开心心想着我要学习啦,然后兴高采烈打开了比火星文还火星文的字符-- 没事,我可以搞定这堆鬼画符. 先来讲一下为什么有乱码这种东西的存在 故事是这样滴: 字符串是Pyth ...

  8. 太白老师 day06 编码 encode decode

    ASCII : 字母, 数字, 特殊字符 字符:1个字节 数字: 1个字节 Unicode: 万国码, 包含所有文字 创建之初 字符: 2个字节 中文: 2个字节 升级: 字符: 4个字节 中文 : ...

  9. Python编码介绍——encode和decode

    在 python 源代码文件中,如果你有用到非ASCII字符,则需要在文件头部进行字符编码的声明,声明如下: # code: UTF-8 因为python 只检查 #.coding 和编码字符串,所以 ...

随机推荐

  1. python day17面向对象-组合

    组合: 给一个类的对象封装一个属性,这个属性是另一个类的对象. class GameRole: def __init__(self, name, ad, hp): self.name = name s ...

  2. 使用Chrome调试工具抢阿里云免费套餐

    活动地址如下: https://free.aliyun.com/ntms/free/experience/getTrial.html 首先打开地址,需要登录,登陆后看到如下页面: 选择个人免费套餐,这 ...

  3. 单臂路由实现VLAN间通信

    实验要求:利用路由器完成同vlan能通信,不同vlan也能通信 拓扑如下: 涉及内容有: 1.VTP的创建和配置 2.VLAN的创建和划分 3.路由器的单臂路由配置 配置如下: route1 enab ...

  4. 添加aimate动画

    .page3_ship{ background:url(../image/boat_02.png) 0 center no-repeat; background-size: 486px 385px; ...

  5. MySQL主从、环境搭建、主从配制

    1. MySQL主从介绍    2.环境搭建   2.主从配制:修改主配制文件:vim /etc/my.cnf添加: server_id = ###log_bin = diy_name然后保存重启:/ ...

  6. js-自加和自减

    i++ 返回的是自增之前的值    先利用再加 ++i 返回的是自增之后的值    先加再利用

  7. rest-framework之频率控制

    rest-framework之频率控制 本文目录 一 频率简介 二 自定义频率类,自定义频率规则 三 内置频率类及局部使用 四 内置频率类及全局使用 五 源码分析 回到目录 一 频率简介 为了控制用户 ...

  8. Django---模版层

    ---https://www.cnblogs.com/liuqingzheng/articles/9509806.html 一.处理浏览器转义字符串的两种方式 1.{{ str|safe }} 2.在 ...

  9. 【BZOJ3672】【UOJ#6】【NOI2014】随机数生成器

    暴力出奇迹 原题: 2≤N,M≤5000 0≤Q≤50000 0≤a≤300 0≤b,c≤108 0≤x0<d≤108 1≤ui,vi≤N×M 恩首先容易看出来这个棋盘直接模拟搞出来就行了,不用 ...

  10. 用Git向gitHub上传项目

    用Git向gitHub上传项目 1.安装git 2.在git安装目录下,运行git-bash.exe  如图所示 3.在git中绑定你注册gitHub是的用户名.邮箱. $ git config -- ...