以下转自于:wklken的博客,写的非常好的一段有关编码的总结。

Python-进阶-编码处理小结

整理下python编码相关的内容

注意: 以下讨论为Python2.x版本, Py3k的待尝试


开始

用python处理中文时,读取文件或消息,http参数等等

一运行,发现乱码(字符串处理,读写文件,print)

然后,大多数人的做法是,调用encode/decode进行调试,并没有明确思考为何出现乱码

所以调试时最常出现的错误

错误1

  1. Traceback (most recent call last):
  2. File "<stdin>", line 1, in <module>
  3. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
  4.  

错误2

  1. Traceback (most recent call last):
  2. File "<stdin>", line 1, in <module>
  3. File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
  4. return codecs.utf_8_decode(input, errors, True)
  5. UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
  6.  

首先

必须有大体概念,了解下字符集,字符编码

ASCII | Unicode | UTF-8 | 等等

字符编码笔记:ASCII,Unicode和UTF-8

淘宝搜索技术博客-中文编码杂谈


str 和 unicode

str和unicode都是basestring的子类

所以有判断是否是字符串的方法

  1. def is_str(s):
  2. return isinstance(s, basestring)
  3.  

str和unicode 转换

decode 文档

encode 文档

  1. str  -> decode('the_coding_of_str') -> unicode
  2. unicode -> encode('the_coding_you_want') -> str
  3.  

区别

str是字节串,由unicode经过编码(encode)后的字节组成的

声明方式

  1. s = '中文'
  2. s = u'中文'.encode('utf-8')
  3. >>> type('中文')
  4. <type 'str'>
  5.  

求长度(返回字节数)

  1. >>> u'中文'.encode('utf-8')
  2. '\xe4\xb8\xad\xe6\x96\x87'
  3. >>> len(u'中文'.encode('utf-8'))
  4. 6
  5.  

unicode才是真正意义上的字符串,由字符组成

声明方式

  1. s = u'中文'
  2. s = '中文'.decode('utf-8')
  3. s = unicode('中文', 'utf-8')
  4. >>> type(u'中文')
  5. <type 'unicode'>
  6.  

求长度(返回字符数),在逻辑中真正想要用的

  1. >>> u'中文'
  2. u'\u4e2d\u6587'
  3. >>> len(u'中文')
  4. 2
  5.  

结论

搞明白要处理的是str还是unicode, 使用对的处理方法(str.decode/unicode.encode)

下面是判断是否为unicode/str的方法

  1. >>> isinstance(u'中文', unicode)
  2. True
  3. >>> isinstance('中文', unicode)
  4. False
  5. >>> isinstance('中文', str)
  6. True
  7. >>> isinstance(u'中文', str)
  8. False
  9.  

简单原则:不要对str使用encode,不要对unicode使用decode (事实上可以对str进行encode的,具体见最后,为了保证简单,不建议)

  1. >>> '中文'.encode('utf-8')
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
  5. >>> u'中文'.decode('utf-8')
  6. Traceback (most recent call last):
  7. File "<stdin>", line 1, in <module>
  8. File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
  9. return codecs.utf_8_decode(input, errors, True)
  10. UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
  11.  

不同编码转换,使用unicode作为中间编码

  1. #s是code_A的str
  2. s.decode('code_A').encode('code_B')
  3.  

文件处理,IDE和控制台

处理流程,可以这么使用,把python看做一个水池,一个入口,一个出口

入口处,全部转成unicode, 池里全部使用unicode处理,出口处,再转成目标编码(当然,有例外,处理逻辑中要用到具体编码的情况)

  1. 读文件
  2. 外部输入编码,decode转成unicode
  3. 处理(内部编码,统一unicode)
  4. encode转成需要的目标编码
  5. 写到目标输出(文件或控制台)
  6.  

IDE和控制台报错,原因是print时,编码和IDE自身编码不一致导致

输出时将编码转换成一致的就可以正常输出

  1. >>> print u'中文'.encode('gbk')
  2. ????
  3. >>> print u'中文'.encode('utf-8')
  4. 中文
  5.  

建议

规范编码

统一编码,防止由于某个环节产生的乱码

环境编码,IDE/文本编辑器, 文件编码,数据库数据表编码

保证代码源文件编码

这个很重要

py文件默认编码是ASCII, 在源代码文件中,如果用到非ASCII字符,需要在文件头部进行编码声明 文档

不声明的话,输入非ASCII会遇到的错误,必须放在文件第一行或第二行

  1. File "XXX.py", line 3
  2. SyntaxError: Non-ASCII character '\xd6' in file c.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
  3.  

声明方法

  1. # -*- coding: utf-8 -*-
  2. 或者
  3. #coding=utf-8
  4.  

若头部声明coding=utf-8, a = '中文' 其编码为utf-8

若头部声明coding=gb2312, a = '中文' 其编码为gbk

so, 同一项目中所有源文件头部统一一个编码,并且声明的编码要和源文件保存的编码一致(编辑器相关)

在源代码用作处理的硬编码字符串,统一用unicode

将其类型和源文件本身的编码隔离开, 独立无依赖方便流程中各个位置处理

  1. if s == u'中文':  #而不是 s == '中文'
  2. pass
  3. #注意这里 s到这里时,确保转为unicode
  4.  

以上几步搞定后,你只需要关注两个 unicode和 你设定的编码(一般使用utf-8)

处理顺序

  1. 1. Decode early
  2. 2. Unicode everywhere
  3. 3. Encode later
  4.  

相关模块及一些方法

获得和设置系统默认编码

  1. >>> import sys
  2. >>> sys.getdefaultencoding()
  3. 'ascii'
  4. >>> reload(sys)
  5. <module 'sys' (built-in)>
  6. >>> sys.setdefaultencoding('utf-8')
  7. >>> sys.getdefaultencoding()
  8. 'utf-8'
  9.  

str.encode('other_coding')

在python中,直接将某种编码的str进行encode成另一种编码str

  1. #str_A为utf-8
  2. str_A.encode('gbk')
  3. 执行的操作是
  4. str_A.decode('sys_codec').encode('gbk')
  5. 这里sys_codec即为上一步 sys.getdefaultencoding() 的编码
  6.  

'获得和设置系统默认编码'和这里的str.encode是相关的,但我一般很少这么用,主要是觉得复杂不可控,还是输入明确decode,输出明确encode来得简单些(个人观点)

chardet

文件编码检测,下载

  1. >>> import chardet
  2. >>> f = open('test.txt','r')
  3. >>> result = chardet.detect(f.read())
  4. >>> result
  5. {'confidence': 0.99, 'encoding': 'utf-8'}
  6.  

\u字符串转对应unicode字符串

  1. >>> u'中'
  2. u'\u4e2d'
  3. >>> s = '\u4e2d'
  4. >>> print s.decode('unicode_escape')

  5. >>> a = '\\u4fee\\u6539\\u8282\\u70b9\\u72b6\\u6001\\u6210\\u529f'
  6. >>> a.decode('unicode_escape')
  7. u'\u4fee\u6539\u8282\u70b9\u72b6\u6001\u6210\u529f'
  8.  

python unicode文档

入口


好了,暂时就这么多,希望讲清楚了

thx

wklken

2013-08-31 于深圳

转载、Python的编码处理(二)的更多相关文章

  1. python字符编码(二)

    一.什么是字符编码 计算机要想工作必须通电,也就是说‘电’驱使计算机干活,而‘电’的特性,就是高低电压(高低压即二进制数1,低电压即二进制数0),也就是说计算机只认识数字 编程的目的是让计算机干活,而 ...

  2. python字符串编码理解(转载)

    (转载)字符编码和python使用encode,decode转换utf-8, gbk, gb2312 (http://www.cnblogs.com/jxzheng/p/5186490.html) A ...

  3. 【转载】不得不知道的Python字符串编码相关的知识

    原文地址:http://www.cnblogs.com/Xjng/p/5093905.html 开发经常会遇到各种字符串编码的问题,例如报错SyntaxError: Non-ASCII charact ...

  4. python --- 字符编码学习小结(二)

    距离上一篇的python --- 字符编码学习小结(一)已经过去2年了,2年的时间里,确实也遇到了各种各样的字符编码问题,也能解决,但是每次都是把所有的方法都试一遍,然后终于正常.这种方法显然是不科学 ...

  5. 不得不知道的Python字符串编码相关的知识

    开发经常会遇到各种字符串编码的问题,例如报错SyntaxError: Non-ASCII character 'ascii' codec can't encode characters in posi ...

  6. Python字符编码以及循环机制介绍

    Python字符编码以及循环机制介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 身为一名运维人员就得不断的学习,那么如何身为运维的你是否已经嗅探已经很火的Python编程啦?大 ...

  7. python异步IO编程(二)

    python异步IO编程(二) 目录 开门见山 Async IO设计模式 事件循环 asyncio 中的其他顶层函数 开门见山 下面我们用两个简单的例子来让你对异步IO有所了解 import asyn ...

  8. [转载]Python 资源大全中文版

    [转载]Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-python 是 vinta 发起维护的 Python ...

  9. Python的单元测试(二)

    title: Python的单元测试(二) date: 2015-03-04 19:08:20 categories: Python tags: [Python,单元测试] --- 在Python的单 ...

  10. [转载]Python 资源大全

    原文链接:Python 资源大全 环境管理 管理 Python 版本和环境的工具 p – 非常简单的交互式 python 版本管理工具. pyenv – 简单的 Python 版本管理工具. Vex  ...

随机推荐

  1. CentOS Maven 删除 *.lastUpdated文件

    find . -name "*.lastUpdated" -exec rm -rf {} \;

  2. sql典例分析

    1. 条件过滤 & Having 表结构 #tab_a #tab_b 表关系 tab_a.id = tab_b.relation_id 表数据 需求 查新把tab_a的ID对应的表tab_b的 ...

  3. elasticsearch java使用

    本文将介绍如何使用java调用elasticsearch的api 1.获取client连接 package com.test.elasticsearch; import java.net.InetAd ...

  4. 下拉框多选实现回显及sql

    <td class="tabTd"><label>客户来源:</label></td> <td><select c ...

  5. Unity主线程和子线程跳转调用(2)

    在上一篇介绍了多线程和Unity交互方式,但是由于我的项目是一个unity编辑器插件项目,很显然上一篇的代码需要加以修改,在编辑器下实现Loom. 1,Editor下的没有Update这个生命周期函数 ...

  6. SSH框架搭建步骤总结以及Hibernate二级缓存,查询缓存

    二级缓存.查询缓存 一级缓存: 默认启动,生命周期是和session同步的,session独享 二级缓存: 需要加载配置信息,生命周期是和应用服务器同步,session共享 1:在hibernate. ...

  7. winform绑定多张图片

    开发winform程序的时候经常设计到要显示多张图片的问题,其解决思路一般是先遍历文件夹中的所有图片,然后再把这些图片添加到ImageList控件中,最后再绑定显示出来.这里我们介绍两种绑定的方法: ...

  8. [android] 手机卫士接收打电话广播显示号码归属地

    使用广播接收者接收打电话的意图,显示号码归属地 新建一个类OutCallReceiver继承系统的BroadcastReceiver 重写onReceive()方法 调用getResultData() ...

  9. Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结

    Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结 这两天闲着没事想利用**Spring Boot**加上阿里的开源数据连接池**Druid* ...

  10. win Apache服务消失或无法启动

    在bin目录中找到httpd.exe命令,如下图所示.启动cmd,即命令行,使用管理员身份运行,cd至该bin目录下.   使用cmd执行如下命令进行服务的安装:httpd.exe -k instal ...