溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python中編碼機(jī)制的相關(guān)問題

發(fā)布時間:2021-08-25 11:46:46 來源:億速云 閱讀:115 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Python中編碼機(jī)制的相關(guān)問題的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

問題1:問題在哪里?

問題是我們的靶子,心中沒有問題去學(xué)習(xí)就會抓不住重點。

本文使用的編程環(huán)境是centos6.7,python2.7。我們在shell中鍵入python以打開python命令行,并鍵入如下兩句話:

 s = "中國zg"
 e = s.encode("utf-8")

現(xiàn)在的問題是:這段代碼能運(yùn)行嗎?

答案是不能,會報如下的錯:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

請留意一下錯誤中說明的0xe4,它是我們分析錯誤的突破口。

相信很多人都遇到過這個錯誤。那么新的問題來了。

問題2:Why?

要搞清楚原因,我們不妨認(rèn)真分析下這兩句話的執(zhí)行流程:

首先,我們通過鍵盤在python命令行解釋器中鍵入了 中國zg 并且給它加上了英文的雙引號,然后又賦值給了變量s,看起來很稀松平常是不是?其實里面大有玄機(jī)。

當(dāng)我們通過鍵盤在程序中輸入字符時,我們是通過操作系統(tǒng)完成這個功能的。我們在屏幕上看到的 中國zg 實際上是操作系統(tǒng)給我們?nèi)祟惖囊粋€反饋,告訴你:“嗨,哥們,你在程序中輸入了字符 中國zg ”

那操作系統(tǒng)給程序的反饋是什么呢?答案就是01串,這個01串是什么樣子,又是怎么生成的呢?

答案就是操作系統(tǒng)使用自己的默認(rèn)編碼方式,將中國zg進(jìn)行了編碼,并把編碼后的01串給了程序。

我們用的centos系統(tǒng)默認(rèn)的編碼是utf-8,所以,只要知道中國zg每個字符的utf-8的編碼就可以知道01串是什么了。

查詢后,可以獲得它們的編碼是(以16進(jìn)制和2進(jìn)制表示):

zg
E4B8ADE59BBD7A67
11100101 10011011 1011110111100101 10011011 101111010111101001100111

現(xiàn)在我們知道操作系統(tǒng)傳給程序的01串長什么樣子了。然后,程序會怎么處理它呢?

程序看到這個01串被雙引號包圍著,自然知道這個01串是一個字符串。然后這個字符串被賦值給了s。

到此,就是第一句的執(zhí)行邏輯。

現(xiàn)在繼續(xù)進(jìn)行第二句的執(zhí)行。

e = s.encode("utf-8")的意思是將字符串s用utf-8進(jìn)行編碼,并將編碼后的字符串賦值給e。問題來了,程序現(xiàn)在知道s中的01串,還知道這個01串表示的是字符串,但這個字符串的編碼是什么呢?我們必須知道01串的現(xiàn)有編碼才能解析出里面的字符,也才能用新的編碼方式,如utf-8來重新編碼它。操作系統(tǒng)只給程序傳來了01串,并沒有告訴程序這個01串用的字符編碼是什么。

此時,python程序就會用它自己默認(rèn)的編碼當(dāng)作s的編碼,進(jìn)而來識別s中的內(nèi)容。這個默認(rèn)的編碼是ASCII,所以,它會用ASCII來解釋這個01串,識別出字符串的內(nèi)容,再將這個字符串轉(zhuǎn)為utf-8編碼。

好了,程序碰到的第一個字節(jié)就是E4(11100101 ),傻眼! ASCII編碼中沒有這玩意兒,因為ASCII編碼中字節(jié)第一位都是0。

怎么辦?

報錯唄,于是我們就看到了上面的錯誤。

錯誤中的0xe4就是字符 “中” 的utf8編碼的第一個字節(jié)。

問題3:How?

知道問題出在哪里了,怎么解決這個問題呢?

顯然,我們只要告訴程序,這個s中的01串的編碼是utf-8,程序就應(yīng)該能正確工作。

但這樣的解決方法有一個問題,就是不夠通用。

假如我有個程序,它要讀取很多文本文件,每個文本文件的編碼都不一樣,豈不是針對每個讀進(jìn)來的文件都維護(hù)一個編碼信息?很繁瑣。

進(jìn)一步,如果這些文本文件的內(nèi)容還要做相互的比較連接之類的操作,編碼都不一致,豈不是更麻煩?

python是怎么聰明地解決這個問題的呢?

很簡單,就是decode!

decode的意思是說,你有一個字符串,并且你知道它的編碼,只要你用該編碼decode這個字符串,那么,python就會識別出里面的字符內(nèi)容,同時,建一個int數(shù)組,將每個字符的unicode序號存進(jìn)去。

所有的字符串都這樣做,就可以確保在程序運(yùn)行過程中,各種來源獲得的字符串都有一樣的表示。它們就可以方便地進(jìn)行各種操作了。

上面說的 int數(shù)組會被python封裝成一個對象,即unicode對象。

問題4:如何搞定?

下面,我們在python命令行中輸入如下兩行代碼:

e = s.decode("utf-8")
isinstance(e,unicode)

程序的輸出是True,這說明,decode后返回的e確實是一個unicode對象。

unicode在這里是一個類,是python里面的類。

e 被稱作unicode字符串,意思是說,它存的是字符的unicode序號,并沒有使用任何編碼。

然后,我們就可以將e編碼成任意一種編碼,比如下面的操作都是可以的

e.encode("utf-8")
e.encode("gbk")

只要你選擇的編碼能夠?qū)中的字符進(jìn)行編碼即可,如果不能編碼,就會報錯。

比如,如果你嘗試這樣:

e.encode("ascii")

由于ASCII并不能編碼 中國 這兩個字符,所以會爆出 encode error。

至此,我們已經(jīng)看到了兩種錯誤,decode error 和encode error,并解決了它們。

問題5:如何評價python的這種字符編碼處理方法?

首先,這樣的處理方法非常的簡單。任何文本,只要它進(jìn)入程序時進(jìn)行一次decode,就會變成unicode對象,里面用int存著每個字符的unicode序號。只要在這個文本要輸出時再進(jìn)行一次encode,編碼成我們需要的編碼就可以了。

問題是,所有的字符都用一個int來表示會不會太浪費空間?畢竟,用ASCII編碼,英文的字符只要一個字節(jié)就可以了。

確實會費點空間,但是現(xiàn)在的內(nèi)存都足夠大,而且我們只在程序內(nèi)部使用這種方式,當(dāng)字符串要寫入文件或者通過網(wǎng)絡(luò)傳輸時,我們都會進(jìn)行相應(yīng)的編碼的。

還有一個問題,那些寫死在程序中的字符串怎么辦?難道每次使用都要進(jìn)行一次decode?不同的操作系統(tǒng)默認(rèn)使用的編碼是不一樣的,當(dāng)我們在linux下,通常需要用utf8做decode,在Windows下,通常需要用gbk做 decode。這樣,我們的代碼就只能在特定的平臺運(yùn)行。

python給我們提供了一個很簡單的辦法,只要在字符串前面加一個u,它就會幫我們探測系統(tǒng)的編碼,并自動完成decode。

問題6:總結(jié)下,學(xué)到了什么?

本文用一個很常見的錯誤為起點,詳細(xì)分析了python中的編碼問題。我們看到了python處理字符問題的簡單之處,也能夠理解為什么python有這么強(qiáng)大的文本處理功能。

測試題:看你是否真正理解了。

假設(shè)一臺linux上有一個文件a.txt,里面的內(nèi)容是"中文"兩個字符,編碼方式是utf-8。

現(xiàn)在,在python程序中寫如下語句:

import codec
s=""
with codec.open("a.txt",encoding="utf-8") as f:
s=f.readline().strip()
with open("b.txt","w") as f:
f.write(s)

請問這段代碼能執(zhí)行嗎?為什么?

答案:不能!

s底下的表示是unicode,寫出時python會對其進(jìn)行編碼,默認(rèn)用的ascii編碼無法對"中文"兩個字符進(jìn)行編碼,所以會報錯!

感謝各位的閱讀!關(guān)于“Python中編碼機(jī)制的相關(guān)問題”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI