徹底搞清楚python字符編碼


 

在討論python編碼之前,我先了解了幾種編碼的由來。

一、編碼類型

1、ascci碼

ascci碼由美國人發明,用1個字節(byte)存儲英文和字符,前期用了128個,后來新加了其他歐洲國家的符號,128~255這一段。
256個字符,基本上就是鍵盤上的所有字符。

2、unicode

2個byte,65535。因為后來發現還有其他國家的語言,而256個字符太少。

3、utf-8

UTF-8是Unicode的實現方式之一。
UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。
UTF-8的編碼規則很簡單,只有二條:

  • 對於單字節的符號,字節的第一位設為0,后面7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
  • 對於n字節的符號(n>1),第一個字節的前n位都設為1,第n+1位設為0,后面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的unicode碼。

下表總結了編碼規則,字母x表示可用編碼的位。


Unicode符號范圍         |       UTF-8編碼方式
(十六進制)                    |       (二進制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

 

4、GBK

GBK全稱《漢字內碼擴展規范》(GBK即“國標)就是國家制定的標准。

其實GBK在就是將每個漢字對應一個數字編碼,http://www.mytju.com/classCode/tools/encode_gb2312.asp 這個網址可以查看到具體的編碼對應關系:

比如:中國  二字,對應的各種編碼如下。

 

 

二、為什么要轉碼?

在python程序運行過程中,如果遇到編碼不一致(就好像中國人和美國人在一起,如果語言不通的話,就無法溝通。),就需要進行轉碼。相當於需要有一個翻譯。

在運行Python程序的過程中,會涉及到三個方面的編碼:

  1. Python程序文件本身的編碼(test.py文件的編碼)--自身文件

  2. Python程序運行時環境的編碼(比如securecrt,類似mysql客戶端連接時的編碼)--客戶端
  3. Python程序讀取外部文件的編碼(引用外部文件的編碼)--外部文件

下面對於以上三種情況為什么需要轉碼分別進行說明:

情況一(自身文件編碼問題)

python2默認編碼為ascii,如果我們寫的代碼里面有非ascii字符,比如中文字符,py程序就會不認識。

就相當於兩個人都用普通話在溝通,其中某一個人突然蹦出一句家鄉話,另外一個人突然就懵逼了,同樣,python也懵逼了。

記得剛開始接觸python時,就碰到了經典錯誤,然后網上各種找資料,后來照着網上前輩們的設置,也沒有深究其原理。

經典錯誤范例:

#!/usr/bin/env python

print '你好 大鳥'

運行時會報錯:

SyntaxError: Non-ASCII character '\xe4' in file t.py on line 4, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

錯誤原因:python2默認的編碼為ascii,python3默認編碼為utf-8,而文件里面包含了非ASCII字符,所以他肯定不認識,就報錯了。

可以通過sys模塊查看默認編碼:

>>> sys.getdefaultencoding()
'ascii'

怎么解決?

針對情況一解決方法:(目的都是將默認編碼修改成utf-8,這樣,程序既可以認識ascii,又可以認識utf-8了)

解決方法一:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
解決方法二:
#coding:utf8
解決方法三:
#-*- coding:utf-8 -*-

  

 

情況二(客戶端編碼問題) 

我們在使用mysql時,如果客戶端設置為latin,而服務端為utf-8,查詢內容有中文時,就會出現亂碼。同樣,我們在使用python時,secureCRT也是客戶端,服務端就是我們連接的服務器。

范例:

1、客戶端設置secureCRT編碼為UTF-8

 

2、服務端測試

 

3、設置客戶端為非utf-8時,就會出現亂碼

 

結果如下:

而且從步驟2中也可以看出,python自動識別變量a='中國test'為utf-8的編碼,如果客戶端(secureCRT)和服務端(python)編碼不一致時,就會出現亂碼。

情況二解決辦法:設置客戶端的編碼格式和服務端一致!

 

情況三:讀取外部文件時,出現亂碼

比較典型的就是:當我們從windows上編輯一個文件,上傳到linux上時,會驚奇的發現^M符號。這個就是因為windows和linux的回車換行符不一致導致的,此時如果是python文件時,python也會報錯。

 

我們在linux先查看時會有特殊符號:

這時,如果我們需要去掉^M,需要使用dos2unix工具轉換一下,去掉windows上的格式。

 

三、編碼怎么轉換

unicode為橋梁,utf-8和gbk互轉需要經過unicode這個翻譯,不然他們二者是無法直接溝通。

 

操作范例:

1、查看默認編碼,python遇到中文字符,會識別他是utf-8編碼,chardet模塊可以識別編碼格式,但是也不是100%,下面他識別出myname為utf-8的概率為75%。

2、將utf-8轉為unicode編碼

utf-8轉為unicode編碼是,需要指定他本身是什么格式的編碼,類似於加密。查看myname_unicode變量時,發現他是unicode編碼格式了。

3、將unicode編碼轉為utf-8

具體轉換操作如下:

 

 例子:

>>> a=u'中國'  #unicode編碼格式的字符串
>>> a_utf8=a.encode('utf-8')  #將unicode轉成utf-8編碼格式
>>> a_utf8
'\xe4\xb8\xad\xe5\x9b\xbd'
>>> a_unicode=a_utf8.decode('utf-8') #從utf8編碼格式轉回unicode編碼格式
>>> a_unicode
u'\u4e2d\u56fd'
>>> a
u'\u4e2d\u56fd'
>>>
>>> b_gbk=a_unicode.encode('gbk')  #將上面unicode格式的轉成gbk編碼格式
>>> b_gbk
'\xd6\xd0\xb9\xfa'
>>> b_unicode=b_gbk.decode('gbk') #轉回unicode編碼格式
>>> b_unicode   #最后發現,a_unicode、b_unicode和原始的unicode編碼的a都相等。
u'\u4e2d\u56fd'
>>> a_unicode
u'\u4e2d\u56fd'
>>> a
u'\u4e2d\u56fd'
>>> 

 

a.encode(* *):將a 編碼 為 * *編碼格式的字符串或unicode對象

a.decode(* *):將a 解碼 為 unicode編碼格式的字符串或unicode對象

 另外:

Python將字符串格式的unicode編碼轉換成unicode編碼,如:\u53eb\u6211,需要轉換成中文時有兩種方式

1.使用eval:

eval("u"+"\'"+unicodestr+"\'")

2.使用decode:

str1 = '\u4f60\u597d'  
print str1.decode('unicode_escape')  
你好 

unicodestr.decode('unicode_escape')  # 將轉義字符\u讀取出來

四、參考文獻和文件索引 

1、漢字對應表:http://www.chi2ko.com/tool/CJK.htm

2、阮一峰的網站

 


免責聲明!

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



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