給自己與初學者關於decode,encode的建議(啥utf-8,GBK)。


2021-01-18更新

 參考鏈接:https://www.bilibili.com/video/BV1Sp4y1U7Jr?p=160

最近一直空的時候看一些老男孩的教學視頻,對基礎的Python知識查漏補缺。

剛看到字符的解碼與編碼問題,記錄一些我自己的學習感悟吧。

當我們在終端輸出看到的,包括一些文本編輯器看到的,理論上面都是Unicode的字符串形式。

當我們打開一個文本文件的時候,必須用一直指定的編碼形式來解碼文件中的數據,你可以用各種不同的編碼集,但正確的應該是你寫入硬盤的時候的編碼集。

說到底,文字還是給人看的,計算機最終的保存還是二進制的文件,在20世紀90年代,為了創造一種能包含全球文字的字符集出現了,那就是Unicode。

計算機啟動后,內存中應該運行這個Unicode字符集的類似與mapping的程序,這是一個大型的中轉站,因為現在的計算機必須要基本的需求,能夠顯式各種文字。

所以Unicode的每一個字都又對應的不同字符集的對應的編碼,可以理解為Unicode的每一個字為key,不同的字符集的編碼為value,而且是一對多的。

好比一個中文字"好"的Unicode編碼為'\u597d',他針對不同的字符集有着不同的對應編碼。

我說的是假如:GBK下面對應的是\x1122,這樣的話,如果通過GBK的方式保存在電腦的話數據就是\x1122,但打開的時候通過GBK解碼,會找到對應Unicode的編碼,從而顯式正常的數值。

按照現在的趨勢來看,后續的任何文本操作都應該保存為utf8格式,因為utf8是Unicode的一種轉換表達,簡單理解utf8與Unicode的編碼存在一一對應的關系。

但另外的字符集可能就會出現問題,中國的字符集不能編碼日文,從而不能保存有日文的信息。

 

對於不能理解字符集相關知識的朋友,記住一點就夠了,就是從現在開始,任何的文本文件都用utf8進行操作與保存就對了。在計算機內部Unicode的暫存是因為給另外的編碼集當中轉站使用。

 

 

 

 

學了不少時間了,對於字符串的編碼與解碼總算有了一些認識。

記錄一些自己的想法。

首先,在Python3里面,我們的str類型,相當於Python2的中unicode。

>>> name = '四店'
>>> name
'\xe5\x9b\x9b\xe5\xba\x97'
>>> uname = name.decode('utf-8')
>>> print name
四店
>>> print uname
四店
>>> uname
u'\u56db\u5e97'
>>> type(uname)
<type 'unicode'>
>>> type(name)
<type 'str'>

 上面的是在python2中運行的結果,可以看到終端模式下,輸入字符串對象只會出來對象的字節碼數據,只有在print輸出的時候,才出現對應的文字。

但在Python3中完全不一樣了,py3的str就是py2的unicode

In [663]: name = u'\u56db\u5e97'                                                                                        

In [664]: name                                                                                                          
Out[664]: '四店'

In [665]: uname = name.encode('utf8')                                                                                   

In [666]: uname                                                                                                         
Out[666]: b'\xe5\x9b\x9b\xe5\xba\x97'

In [667]: print(name)                                                                                                   
四店

In [668]: print(uname)                                                                                                  
b'\xe5\x9b\x9b\xe5\xba\x97'

在這里可以看到,我們賦值給name的unicode的字符標識,但無論是終端還是print輸出,name一直是四點了。

name明顯是str模式,所以證明了前面說的。

 

后面流暢的Python我會記錄自己的更加詳細對與解碼,編碼的理解。

 

其實想通了感覺也就那么回事,網上好多資料,基本都是一大抄。

 

我最后稍微總結一下。unicode就是一份超級大字典,全世界所有的文字都有,所以Python終端顯示用unicode蠻好

但unicode的對應表,很多人覺的傳輸數據的時候不好,就搞出來了utf-8,utf-16,utf-32,這個也是一份映射表。

假如在unicode里面,每個文字的名字相當與碼位,utf-8,utf-16就好比編號。

比如"好"的unicode為u'\u597d',utf-8為'\xe5\xa5\xbd'

這個一對一對應的,就是說,unicode里面的每一個字符都可以找到utf-8的對應字節序(通俗講就是編號)。

所以大家應該用utf-8。

 

再來說一些地方與國家的編碼,比如中國的gbk,gbk包含了全部的中國字與字節碼的映射關系,可以想象成這是一本,中國的地方字典。

In [669]: name                                                                                                          
Out[669]: '四店'

In [670]: bytes(name,encoding='gbk')                                                                                    
Out[670]: b'\xcb\xc4\xb5\xea'

 當我們在encode的時候,首先先拿gbk對照表里面的字來對比需要解碼的字,比如第一個四字,找到了它的序號為\xcb\xc4,然后對編號進行輸出。

所以這個很容易造成問題,你如果給一個他字符集沒有的字,找了老半天才找到。

In [679]: '\u20ac'.encode('gbk')                                                                                        
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-679-90f6ff568b6b> in <module>
----> 1 '\u20ac'.encode('gbk')

UnicodeEncodeError: 'gbk' codec can't encode character '\u20ac' in position 0: illegal multibyte sequence

In [680]: '\u20ac'                                                                                                      
Out[680]: '€'

 就報錯了,話說gbk的字符集還是蠻厲害了,輸入了日本字,意大利的字,基本都有。

但對於utf-8只要是unicode的字符,他都能編碼

In [680]: '\u20ac'                                                                                                      
Out[680]: '€'

In [681]: '\u20ac'.encode('U8')                                                                                         
Out[681]: b'\xe2\x82\xac'

 所以再次推薦大家以后都用utf-8這樣的話,以后里面的decode,encode的ignore參數都可以不用了。

 

 

這里還有一份老外寫的參考鏈接:https://pycoders-weekly-chinese.readthedocs.io/en/latest/issue5/unipain.html

還行吧,反正我沒咋看懂,應該有很多py2的說明,py2基本沒啥節操過。

 

前面寫的我就不刪除了,從流暢的Python書中指出,Python內置100多種字符編碼。

我的理解就是,當給你一個字符假如是"我",Python的100多種解碼器中能找到"我"的對應的字節序列是不一樣的。

你通過編碼的方式把unicode中的"我"轉換成字節序列,可以是2字節,也可能是3字節。

可以用於計算機的存儲,或者網絡的傳輸,但機器看的懂的,人看不懂,當需要人看的時候,你又需要用同樣的方式把機器的字節序列裝換成人看的懂的。

這個就是解碼。你用什么編碼的,就必須用什么解碼,其實有了utf8,另外的編碼方式真的應該淘汰了。

解碼以后就是unicode了,你可以把unicode想象成就是文字。

但unicode變成文字是在哪里實現,又是如何實現的,網上的資料比較少。所以我只能把unicode想象成文件了,

因為你編碼的時候就是對unicode進行編碼。

 

2020年12月4日補充

一段時間的學習與成長,Python網絡編程書中說到Python的字符串(character)包含了Unicode字符。以前一直對這個不是很懂,很多書籍解釋了,可能是翻譯問題,或者我理解問題,不能很好的理解Unicode與Python中的字符串的意思。我現在的理解,就是Python的字符串,就是一堆Unicode。當你在Python的編輯器環境下,只要看到了字符串內有\u形式的字符,就會通過Unicode字符表找到對應碼點(code point)的字符

這里一些記錄:https://www.zhihu.com/question/26921730/answer/1610972540


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM