您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“python編碼的原理及使用”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“python編碼的原理及使用”吧!
編碼就是為了解決字符和字節(jié)之間的關(guān)系。
分字符和字節(jié)是為了解決人機(jī)之間的關(guān)系,一般人只能讀字符,機(jī)器只能識(shí)別字節(jié)。
字符'a',人能夠識(shí)別,機(jī)器不能識(shí)別,機(jī)器只能識(shí)別字節(jié)。
所以需要一種把字符'a'轉(zhuǎn)換為字節(jié)的技術(shù)。
這種技術(shù)就是編碼,例如我們最常見(jiàn)的ASCII(American Standard Code for Information Interchange)碼,就包含英文字符數(shù)字和一些控制字符。
我們通過(guò)ASCII碼表就可以找到字符'a'對(duì)應(yīng)的數(shù)字為97,這樣我們就可以把字符'a'通過(guò)編碼轉(zhuǎn)換為二進(jìn)制字節(jié)01100001,這樣機(jī)器就能識(shí)別了。
我們一般說(shuō)的編碼,指字符集和字符集中字符對(duì)應(yīng)的值,而不是編碼方式
一般的編碼方式就是字符集中字符的編碼對(duì)應(yīng)的二進(jìn)制
Unicode字符集有所不同,有多種常用的編碼方式,后面詳細(xì)介紹。
因?yàn)橛胁煌娜?,使用了不同的字符,如中?guó)人使用了中文字符,正如你現(xiàn)在讀到的字符一樣,我們?cè)贏SCII碼表中是找不到對(duì)應(yīng)字符的,自然也不能根據(jù)ASCII把字符轉(zhuǎn)換為字節(jié)。
所以我們自己就需要新的編碼方式,來(lái)包含我們自己的字符,從最開(kāi)始的GB2312到GBK,再到GB18030。
同理,其他語(yǔ)言也有自己對(duì)應(yīng)的字符集和編碼。
在國(guó)際化的進(jìn)程中,只玩自己的編碼肯定是不行的,所以需要統(tǒng)一的編碼,就是包含世界字符,這樣只需要在應(yīng)用中使用Unicode碼,就能避免為應(yīng)用做適配。
我們知道編碼是包含字符集和字符集中字符對(duì)應(yīng)的值,一般字符集和對(duì)應(yīng)的值放在一起做為一個(gè)對(duì)應(yīng)編碼的碼表。
Unicode有2個(gè)字符集,UCS-2和UCS-4,因?yàn)閁CS-4兼容UCS-2,所以這里介紹一下UCS-4。
UCS-4使用4字節(jié)編碼,最高位都是0,所以最高字節(jié)的8位有7位有效位。
UCS-4使用最高字節(jié)的7位來(lái)標(biāo)識(shí)組(group),也就是有2^7=128個(gè)組。
UCS-4使用次高字節(jié)來(lái)標(biāo)識(shí)平面(plane),8位共2^8=256個(gè)平面。
UCS-4使用第3字節(jié)來(lái)標(biāo)識(shí)行(row),8位2^8=256行。
UCS-4使用第4字節(jié)來(lái)標(biāo)識(shí)碼位(cell),同理有256個(gè)碼位。
group 0的plane 0被稱作Basic Multilingual Plane(BMP)
UCS-4中,高兩個(gè)字節(jié)為0的碼位被稱作BMP,BMP去掉2個(gè)全為0的高字節(jié)之后,就是2字節(jié)的UCS-2。
通過(guò)上面的介紹我們很容易算出:UCS-2共有2^16=65536個(gè)碼位。
這也是在python2.x中:
import sys print sys.maxunicode
打印的值是65535的原因(從0開(kāi)始,所以最大碼位是65535)。
Unicode計(jì)劃使用了17個(gè)平面,每個(gè)平面65536個(gè)碼位,共有17×65536=1114112個(gè)碼位。
這也是在python3.x中:
import sys print sys.maxunicode
打印的值是1114111的原因
先介紹一下'中文'這2個(gè)字符的相關(guān)編碼:
'中文'的Unicode編碼:\u4e2d\u6587 '中文'的UTF-8編碼:\xe4\xb8\xad\xe6\x96\x87 '中文'的GBK編碼:\xd6\xd0\xce\xc4
下面代碼不是通過(guò)交互程序,而是寫入文件,在cmd執(zhí)行。
print("中文")
加入有文件名為test-encoding.py的文件內(nèi)容如上所示,我們?cè)谥形沫h(huán)境windows下執(zhí)行該文件,就會(huì)得到下面的錯(cuò)誤。
我們可以通過(guò)查看test-encoding.py文件的16進(jìn)制,可以看出test-encoding.py文件使用的是UTF-8編碼,對(duì)比'中文'的編碼得出。
我們也可以看出這不是一個(gè)執(zhí)行時(shí)候的錯(cuò)誤,因?yàn)檫@是一個(gè)SyntaxError,說(shuō)明是一個(gè)語(yǔ)法錯(cuò)誤。
同時(shí)這個(gè)錯(cuò)誤也告訴了我們?cè)?,是因?yàn)橛蟹茿SCII字符,因?yàn)閜ython默認(rèn)的編碼是ASCII,所以不能包含有非ASCII字符。
需要包含非ASCII字符我們需要一點(diǎn)特殊的處理,就是告訴python解釋器,文件使用的編碼方式。
# -*- coding: utf-8 -*- print("中文")
添加的注釋部分是告訴python解釋器使用utf-8方式做為字符與字節(jié)之間的編碼方式。
告訴解釋器使用utf-8編碼就夠了嗎?
顯然不是,因?yàn)檫€涉及到其他的編碼方式,例如我們?cè)赾md中執(zhí)行上面的文件,會(huì)得到輸出
涓枃
上面的輸出值其實(shí)就是'中文'這2個(gè)字符的UTF-8編碼\xe4\xb8\xad\xe6\x96\x87對(duì)應(yīng)的GBK編碼。 可以自己對(duì)照GBK碼表檢查,也可以使用在線轉(zhuǎn)換編碼工具轉(zhuǎn)換驗(yàn)證。
因?yàn)閣indows默認(rèn)的代碼頁(yè)是936,也就是GBK編碼。
可以通過(guò)下面的2中方式解決:
# -*- coding: utf-8 -*- print(u"中文") print(a.decode('utf-8').encode('gbk'))
python2.x默認(rèn)的編碼是ASCII python3.x默認(rèn)的編碼是UTF-8
可以通過(guò)sys.getdefaultencoding()查看默認(rèn)編碼方式
那么默認(rèn)的編碼方式到底是什么?
在有些風(fēng)騷的操作中,可能會(huì)教你使用下面的方式解決亂碼:
# -*- coding: utf-8 -*- import sys print(sys.getdefaultencoding()) reload(sys) sys.setdefaultencoding('utf-8') print(sys.getdefaultencoding()) a = '中文' print(a)
然而這并沒(méi)有什么用,因?yàn)檫@是輸出端的問(wèn)題
那這個(gè)騷操作在什么地方有用呢?
答案是處理unicode的時(shí)候:
# -*- coding: utf-8 -*- import sys print(sys.getdefaultencoding()) # reload(sys) # sys.setdefaultencoding('utf-8') with open(r'F:\tmp\test.txt', 'w') as f: f.write('測(cè)試') f.write(u'測(cè)試')
執(zhí)行上面的代碼,會(huì)得到下面的錯(cuò)誤(2.x):
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
但是把注釋代碼取消注釋,就沒(méi)有問(wèn)題了。
我們來(lái)分析一下: f.write(str)接收的是一個(gè)str類型的參數(shù),u'測(cè)試'是一個(gè)unicode類型。
unicode到str需要encode,字節(jié)和字符之間的轉(zhuǎn)換是需要編碼的,顯然這里使用的是:
u'測(cè)試'.encode(sys.getdefaultencoding())
python 交互式使用的編碼默認(rèn)會(huì)讀取系統(tǒng)的編碼,中文環(huán)境下windows下一般是GBK。
所以我們使用交互式的方式一般是沒(méi)有亂碼的問(wèn)題。
UnicodeEncodeError: 'gbk' codec can't encode character u'\xa0' in position 392477: illegal multibyte sequence
有時(shí)候會(huì)遇到上面的錯(cuò)誤,出現(xiàn)這個(gè)錯(cuò)誤的原因基本都是因?yàn)橛休敵龅絚md的命令,也就是基本是因?yàn)閜rint('xxx')造成的,其中xxx是GBK不兼容的字符。
其實(shí)我們可以很容易的構(gòu)造一個(gè)類似的錯(cuò)誤出來(lái)(2.x):
print('?'.decode("utf-8")) #print('?'.decode("utf-8").encode("gbk"))
在中文環(huán)境下的windows命令行執(zhí)行包含上面代碼的文件就會(huì)看到UnicodeEncodeError錯(cuò)誤。
Unicode編碼中: 基本漢字范圍:4E00-9FA5(20902個(gè)) 基本漢字補(bǔ)充:9FA6-9FEF(74個(gè)) ?的Unicode碼是:9FA6,GBK中是沒(méi)有包含?這個(gè)字的
解決辦法: 出現(xiàn)這個(gè)錯(cuò)誤,就說(shuō)明包含有超出GBK范圍的字符了,所以就不要使用GBK編碼方式了。
中文windows命令行默認(rèn)GBK,不修改代碼頁(yè)肯定有這個(gè)問(wèn)題,只有修改代碼頁(yè)才能解決。
換種思路直接輸出到文件,使用UTF-8編碼不是挺好的。
#a是字符串(str)類型 a = '中文' #b是unicode類型 b = u'中文'
2者的不同之處在于:
str類型使用的是系統(tǒng)默認(rèn)編碼(可設(shè)置)
unicode的類型使用的是unicode的編碼
轉(zhuǎn)換: str通過(guò)decode可以獲取到unicode類型 unicode的通過(guò)encode得到str類型
2.x默認(rèn)使用的是ASCII做字符與字節(jié)之間的編碼轉(zhuǎn)換,使用的字符集是UCS-2。
因?yàn)?.x沒(méi)有byte類型,所以不同編碼之間要轉(zhuǎn)換先存儲(chǔ)為unicode編碼,然后需要什么編碼,再?gòu)膗nicode編碼轉(zhuǎn)換為對(duì)應(yīng)的編碼。
相比于2.x,3.x版本就正常多了,和其他語(yǔ)言的邏輯保持了一致性。
首先最重要的是添加了byte類型,即字節(jié)類型。
不再顯示的使用unicode編碼,而是遵從:
字符<--->編碼<--->字節(jié)
#字符--->編碼--->字節(jié) bs = "中文".encode('utf-8') #字節(jié)--->編碼--->字符 ch = bs.decode("utf-8")
3.x默認(rèn)使用utf-8做字節(jié)和字符之間轉(zhuǎn)換的編碼方式,使用的字符集是UCS-4。
亂碼說(shuō)明字節(jié)-->字符的編碼出問(wèn)題了。
所以首先得弄清楚文件、網(wǎng)絡(luò)中的字節(jié)使用的是什么編碼方式,是ASCII、GBK、UTF-8……
然后得弄清楚輸出字符的終端、編輯器是什么編碼,然后對(duì)應(yīng)起來(lái): decode、encode配對(duì)使用一樣的編碼就可以了。
有些朋友可能會(huì)說(shuō),這不是廢話嗎?我知道是什么編碼,還會(huì)亂碼?
問(wèn)題的重點(diǎn)在于:字節(jié)從哪里來(lái),顯示字符的編輯器或終端使用什么編碼。這樣至少可以定位大多數(shù)問(wèn)題。
至于中間經(jīng)過(guò)多次轉(zhuǎn)換的,那就需要仔細(xì)排查了。
到此,相信大家對(duì)“python編碼的原理及使用”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。