Python字符编码入门

Python字符编码入门

字符串、字节串

python中有两个相关类, 他们都是basestring的子类:

  • unicode 字符串,产生来源有: 源码指定u'中国'、外部数据数据库查询结果、读取文本,或者由字节串转换得到 '\xe4\xb8\xad'.decode('utf8') 得到 u'中'
  • string 字节串,产生来源:源码'中国'、由字符经过编码得到的字节串,如
>>> u'中'.encode('gbk')
'\xd6\xd0'
>>> u'中'.encode('utf8')
'\xe4\xb8\xad'

unicode 和 string的转换关系图

python_stringunicode_encode_decode_3.png

注:图中绿色线段标示的即为我们常用的转换方法,红色标示的转换在python 2.x 中是合法的

多种编码解析

  • 系统编码 Unix/Linix 系统通过 locale 查看,windows系统

    系统编码影响到python在控制台REPL模式下的编解码,可以通过 sys.stdin.encodingsys.stdout.encoding 查看Python console从系统继承的默认编解码是什么

  • 默认字符串编码 sys.getdefaultencoding() 官方文档解释

    Return the name of the current default string encoding used by the Unicode implementation.

    可理解为在字节串转化为字符串时,若没有显示指明字节编码方式,都将使用默认编码方式,如:

    • 在源代码文件中没有显示指明 #coding: xxx,解析文件的字节流时使用

    • 在读取文件字节流后,需要转换为字符串时使用

    • 网络请求查询结果返回字节流转换为字符串时使用

      可以通过 reload(sys); sys.setdefaultencoding('utf8') 来改变

  • 源文件代码编码,显示通过文件头两行 #coding: utf-8 来告知python解析器文件的编码,此处的编码应该与实际文件的编码一致,如不指定,根据 PEP 263 将使用 ascii 编码

    Python will default to ASCII as standard encoding if no other encoding hints are given.

    具体python处理文件的过程见 PEP 263 Python's tokenizer/compiler combo will need to be updated to work as follows...

    A. read the file

    B. decode it into Unicode assuming a fixed per-file encoding

    C. convert it into a UTF-8 byte string

    D. tokenize the UTF-8 content

    E. compile it, creating Unicode objects from the given Unicode data and creating string objects from the Unicode literal data by first reencoding the UTF-8 data into 8-bit string data using the given file encoding

  • 文件编码,文件本身的编码,将文件内容按照编码格式存成二进制格式

  • 输入输出编码 sys.stdin.encoding && sys.stdout.encoding

    在控制台时输入输出编码将从系统编码继承,linux下可以通过locale查看,或通过export设置locale
    若字符串

常见错误总结

没有指定source coding encoding

有文件 p233.py,文件编码为utf-8

#!/usr/bin/env python
s = u'é'  # 这里即使注释了也报错
print s

执行 python p233.py 报错如下

SyntaxError: Non-ASCII character '\xc3' in file /Users/yuanzhou/code/PycharmProjects/untitled/test2.py on line 3, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

解释:

>>> u'é'
u'\xe9'
>>> u'é'.encode("utf-8")
'\xc3\xa9'

A: 首先python以二进制流读取文件,由于文件采用utf8编码,因此字节流中存在两个字节\xc3\xa9B: python使用default encoding ascii 将文件字节流转换为python内部的unicode字符集,由于ascii只可以识别0x00-0x7f的字节,因此报错了

如果在p233.py 首行加上 #coding: utf8 重新执行,上面B:将使用utf-8将文件字节流转为python内部的unicode字符集

locale影响python控制台输入和输出

设置 export LC_ALL="C",此时 locale 输出

LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL="C"

此时在控制台下执行以下代码

>>> a=unichr(233)    # 对应latin字符'é'
>>> a, type(a)
(u'\xe9', <type 'unicode'>)
>>> print sys.stdout.encoding
US-ASCII
>>> print a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)
>>> a.encode("utf-8")
'\xc3\xa9'
>>> print a.encode("utf-8")
é

分析报错描述,可以看到报错为UnicodeEncodeError,在读取控制台输入后,print 将结果往stdout输出,因为a变量为unicode,由于stdout.encoding为ascii编码,因此将使用 a.encode("ascii") 以得到字节串,但ascii的范围是0-127,因此抛出异常。通过命令print a.encode("utf-8") 的输出为字节流 \xc3\xa9,此字节流在SSH终端中可以显示的原因是:SSH终端设置编码为UTF-8,可以将此字节流decode为unicode字符

从字符串写到文件异常

>>>a=u'中'
>>>f=open("test.txt", "w")
>>> f.write(a)     # 写入失败,因为sys.getdefaultencoding为ascii
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u4e2d' in position 0: ordinal not in range(128)
>>>f.write(a.encode("utf-8"))  # 写入成功
>>>import sys; reload(sys)
>>>sys.setdefaultencoding("utf-8")
>>>f.write(a)   # 写入成功
>>>f.close()

TO BE CONTINUED

  • 文件名编码, 从db中读取字符是Unicode,open(u, "wb")时抛异常

Reference

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • 字符集和编码简介 在编程中常常可以见到各种字符集和编码,包括ASCII,MBCS,Unicode等字符集。确切的说...
    兰山小亭阅读 8,478评论 0 13
  • 可以看我的博客 lmwen.top 或者订阅我的公众号 简介有稍微接触python的人就会知道,python中...
    ayuLiao阅读 3,106评论 1 5
  • 字符是用户可以读写的最小单位。计算机所能支持的字符组成的集合,就叫做字符集。字符集通常以二维表的形式存在。二维表的...
    刘惜有阅读 8,100评论 2 14
  • 最近总是感到很焦虑,一大堆的事情没完成,导致越堆积越多,人也变得焦虑不安。其实我和很多人一样,老是抱怨没有时间,可...
    莫妮ka阅读 685评论 0 1
  • 徐宏慧大姐著的格格走进务本堂一书,已经拜读完毕。看完近一年,书本放在床头柜上,因为看完时很想写写我对这本书的感想的...
    天使小鱼儿阅读 516评论 1 3