一篇关于STR和UNICODE的好文章

整理下python编码相关的内容

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


开始

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

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

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

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

错误1

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

错误2

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/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 characters in position 0-1: ordinal not in range(128) 

首先

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

ASCII | Unicode | UTF-8 | 等等

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

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


str 和 unicode

str和unicode都是basestring的子类

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

def is_str(s):     return isinstance(s, basestring) 

str和unicode 转换

decode 文档

encode 文档

str  -> decode(‘the_coding_of_str‘) -> unicode unicode -> encode(‘the_coding_you_want‘) -> str 

区别

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

声明方式

s = ‘中文‘ s = u‘中文‘.encode(‘utf-8‘)  >>> type(‘中文‘) <type ‘str‘> 

求长度(返回字节数)

>>> u‘中文‘.encode(‘utf-8‘) ‘\xe4\xb8\xad\xe6\x96\x87‘ >>> len(u‘中文‘.encode(‘utf-8‘)) 6 

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

声明方式

s = u‘中文‘ s = ‘中文‘.decode(‘utf-8‘) s = unicode(‘中文‘, ‘utf-8‘)  >>> type(u‘中文‘) <type ‘unicode‘> 

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

>>> u‘中文‘ u‘\u4e2d\u6587‘ >>> len(u‘中文‘) 2 

结论

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

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

>>> isinstance(u‘中文‘, unicode) True >>> isinstance(‘中文‘, unicode) False  >>> isinstance(‘中文‘, str) True >>> isinstance(u‘中文‘, str) False 

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

>>> ‘中文‘.encode(‘utf-8‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: ‘ascii‘ codec can‘t decode byte 0xe4 in position 0: ordinal not in range(128)  >>> u‘中文‘.decode(‘utf-8‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/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 characters in position 0-1: ordinal not in range(128) 

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

#s是code_A的str s.decode(‘code_A‘).encode(‘code_B‘) 

文件处理,IDE和控制台

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

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

读文件  外部输入编码,decode转成unicode  处理(内部编码,统一unicode)  encode转成需要的目标编码  写到目标输出(文件或控制台) 
【自注】使用print打印到控制台的时候,应该是默认使用了encode()方法

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

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

>>> print u‘中文‘.encode(‘gbk‘) ???? >>> print u‘中文‘.encode(‘utf-8‘) 中文 

建议

规范编码

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

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

保证代码源文件编码

这个很重要

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

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

File "XXX.py", line 3 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 

声明方法

# -*- coding: utf-8 -*- 或者 #coding=utf-8 

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

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

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

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

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

if s == u‘中文‘:  #而不是 s == ‘中文‘     pass #注意这里 s到这里时,确保转为unicode 

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

处理顺序

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

相关模块及一些方法

获得和设置系统默认编码

>>> import sys >>> sys.getdefaultencoding() ‘ascii‘  >>> reload(sys) <module ‘sys‘ (built-in)> >>> sys.setdefaultencoding(‘utf-8‘) >>> sys.getdefaultencoding() ‘utf-8‘ 

str.encode(‘other_coding‘)

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

#str_A为utf-8 str_A.encode(‘gbk‘)  执行的操作是 str_A.decode(‘sys_codec‘).encode(‘gbk‘) 这里sys_codec即为上一步 sys.getdefaultencoding() 的编码 

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

chardet

文件编码检测,下载

>>> import chardet >>> f = open(‘test.txt‘,‘r‘) >>> result = chardet.detect(f.read()) >>> result {‘confidence‘: 0.99, ‘encoding‘: ‘utf-8‘} 

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

>>> u‘中‘ u‘\u4e2d‘  >>> s = ‘\u4e2d‘ >>> print s.decode(‘unicode_escape‘) 中  >>> a = ‘\\u4fee\\u6539\\u8282\\u70b9\\u72b6\\u6001\\u6210\\u529f‘ >>> a.decode(‘unicode_escape‘) u‘\u4fee\u6539\u8282\u70b9\u72b6\u6001\u6210\u529f‘ 

python unicode文档

入口

PYTHON编码处理-str与Unicode的区别的更多相关文章

  1. 转 PYTHON2 编码处理-str与Unicode的区别

    https://www.cnblogs.com/long2015/p/4090824.html

  2. Python中的str与unicode处理方法

    Python中的str与unicode处理方法 2015/03/25 · 基础知识 · 3 评论· Python 分享到:42 原文出处: liuaiqi627 的博客    python2.x中处理 ...

  3. python编码,赋值和is的区别

    1. == 与 is 的区别 赋值 == 比较值是否相等,is 比较,比较的是内存地址. 小数据池的作用是节省内存空间 数字的范围:-5 到 256 共用一个数据池 字符串范围:1.不能有特殊字符.2 ...

  4. [转]Python中的str与unicode处理方法

    早上被python的编码搞得抓耳挠腮,在搜资料的时候感觉这篇博文很不错,所以收藏在此. python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...

  5. python中的str,unicode和gb2312

    实例1: v1=u '好神奇的问题!?' type(v1)->unicode v1.decode("utf-8")# not work,because v1 is unico ...

  6. python中,str和repr的区别

    str函数,它会把值转换为合理形式的字符串,以便用户可以理解. repr会创建一个字符串,它以合法的Python表达式的形式来表示值. 例如: >>> print repr(&quo ...

  7. 【转】Python——编码规范

    来自于 啄木鸟社区 Python Coding Rule --- hoxide 初译 dreamingk 校对发布 040724 --- xyb 重新排版 040915 --- ZoomQuiet M ...

  8. Python 3 中字符串和 bytes 的区别

    在Python中字符串和unicode真是傻傻分不清楚,在没搞懂两个区别时,你会发现程序报的错怎么改都是再报错,让你烦躁. 学习Python的时候,又重温了这部分内容,写了这个学习笔记. Python ...

  9. 系统编码 python编码

    编码一直都是一个很让人头疼的问题,尤其是在python里面.花了几天时间,终于把这个问题给弄明白了. 一,什么是编码,编码过程是怎样的?常见的编码方式有哪些? 编码是从一个字符,比如'哈',到一段二进 ...

随机推荐

  1. MVC学习(三)Code-First Demo

    前面两篇文章介绍了DataBase-First例子,这里就介绍Code-First. 个人简单理解:就是在程序中编写代码,然后在数据库中生成相应的表.字段.约束等等.听上去蛮神奇的.Now,begin ...

  2. vue解决遮罩层滚动方法

    vue 遮罩层阻止默认滚动事件 在写移动端页面的时候,弹出遮罩层后,我们仍然可以滚动页面. vue中提供 @touchmove.prevent 方法可以完美解决这个问题 <div class=& ...

  3. vue 内引入jquery

    1.  npm i jquery -- save 2. import $ from 'jquery' window.$ = $ window.jQuery = $ export default $ 这 ...

  4. python3入门教程

    python : 3.5 jdk : 1.7 eclipse : 4.5.2(有点低了,需要对应Neon 4.6,不然总是会弹出提示框) 应该学习最新版本的 Python 3 还是旧版本的 Pytho ...

  5. POPUP_TO_CONFIRM的使用方法

    CALL FUNCTION 'POPUP_TO_CONFIRM'       EXPORTING         TEXT_QUESTION               = '是否要打印凭证!'    ...

  6. rbac集成 权限分配。之角色管理

    权限分配功能拆分: a. 角色管理 b. 用户管理 c. 菜单和权限的管理 d. 批量的权限操作 e. 分配权限 先实现 角色管理: 无非也就是,增删改查: 定义路由, 编写视图. 1.查看角色页面: ...

  7. netcore sqlserver linq contains生成的sql语句不是使用like而是charIndex

    在ef中使用linq调用了contains,结果怎么都查不到值,打开sqlserver profiler 发现生成的sql语句不是使用like...而是CharIndex 参考文档:https://s ...

  8. js中被调用的函数获取调用者对象

    通过event.srcElement即可.一直用了很久的传参,终于解决了.

  9. Oracle性能优化2- 依据场景选择技术

    1.索引的坏处 索引可以加快查询效率,但是使用不当,会造成插入性能很低 drop table test1 purge; drop table test2 purge; drop table test3 ...

  10. opencv 3.2图像矩(Image Moments)

    图像矩乍看比较难理解,看了很多资料,大概明白了一些,但还是无法在脑海里形成一个模型概念,于是从源码中寻找它的应用. 今天就通过公式和程序抓取数据,来进一步理解图像矩 先看一个图片 这是程序运行结果, ...