編碼基礎python
編碼概述 windows
基本概念很簡單。首先,咱們從一段信息即消息提及,消息以人類能夠理解、易懂的表示存在。我打算將這種表示稱爲「明文」(plain text)。對於說英語的人,紙張上打印的或屏幕上顯示的英文單詞都算做明文。其次,咱們須要能將明文表示的消息轉成另外某種表示,咱們還須要能將編碼文本轉回成明文。從明文到編碼文本的轉換稱爲「編碼」,從編碼文本又轉回成明文則爲「解碼」。python2.7
python解釋器在加載 .py 文件中的代碼時,會對內容進行編碼。python2 默認編碼方式是ascii碼,python3 默認編碼方式utf-8。編輯器
ASCII(American Standard Code for Information Interchange,美國標準信息交換代碼)是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其餘西歐語言,其最多隻能用 8 位來表示(一個字節),即:2**8 = 256-1,因此,ASCII碼最多隻能表示 255 個符號。ide
編碼方式函數
ascii:只能支持英文、特殊字符、數字,用一個字節表示一個字符。最多隻能表示 255 個符號;測試
萬國碼(unicode):全部的字符和符號由4個字節來表示。佔資源較多;(早期全部字符使用2個字節表示,如今已經廢棄)編碼
UTF-8:是對Unicode的升級。UTF-8最少使用一個字節表示一個字符。一個字節表示一個英文字符、2個字節表示一個歐洲字符、3個字節表示一個亞洲字符;spa
gbk:是國人在 ascii 碼的基礎上進行升級的,只支持中文和英文,2個字節表示一箇中文字符,1個字節表示一個英文字符。操作系統
注意:各個編碼之間的二進制是不能互相識別的,會產生亂碼;文件的存儲和傳輸不能是Unicode編碼方式,由於Unicode佔資源較多,只能使用utf8-八、utf8-1六、gbk、gb23十二、ascii等編碼方式才能存儲和傳輸;各個編碼之間的轉換能夠經過unicode這個中間過程進行轉換。(utf8-八、utf8-1六、gbk、gb23十二、ascii等編碼方式統稱爲bytes)
編碼解碼
編碼 encode:將str數據類型轉化成bytes數據類型
解碼 decode:將bytes數據類型轉化成str數據類型
字節串:bytes;字符串:unicode
python2編碼
python2編碼
Python2有兩種數據類型:str和unicode。str數據類型在內存中是用bytes編碼方式存儲的(bytes是utf8-八、utf8-1六、gbk、gb23十二、ascii等編碼方式的統稱)。
#!-*- coding:utf-8 -*- #__author: lriwu # str 在內存中使用bytes編碼方式存儲 s1 = "測試hello" print len(s1) # 11 print repr(s1) # '\xe6\xb5\x8b\xe8\xaf\x95hello' print type(s1) # <type 'str'> # unicode存的是unicode,即字符串 s2 = u"測試hello" print len(s2) # 7 print repr(s2) # u'\u6d4b\u8bd5hello' print type(s2) # <type 'unicode'>
python2編碼的最大特色:Python2 將會自動的將bytes數據解碼成 unicode 字符串
print "測試" # 測試,便可以顯示中文。正常狀況下其實不該該顯示中文,而應該是字節串,之因此顯示中文,緣由是在py 2中自動的將bytes數據類型解碼成 unicode 字符串 print "hello"+u"yuan" # helloyuan ,即byte和unicode能夠進行拼接,Python 2 將會自動的將bytes數據解碼成 unicode 字符串
兩個問題:
一、print "測試" :原本存的是'\xe8\x8b\x91\xe6\x98\x8a',爲何顯示了明文?
正常狀況下其實不該該顯示中文,而應該是字節串(bytes),之因此顯示中文,緣由是在py 2中自動的將bytes數據解碼成 unicode 字符串。
二、字節串和字符串能夠拼接?
這就是那些可惡的 UnicodeError 。代碼中包含了 unicode 和 byte 字符串,只要數據所有是 ASCII 的話,全部的轉換都是正確的,一旦一個非 ASCII 字符偷偷進入你的程序,那麼默認的解碼將會失效,從而形成 UnicodeDecodeError 的錯誤。Python 2 悄悄掩蓋掉了 byte 到 unicode 的轉換,讓程序在處理 ASCII 的時候更加簡單。你復出的代價就是在處理非 ASCII 的時候將會失敗。
print "測試"+u"文本" #字節串和字符串進行拼接 E:\soft_install\python\python2.7\python2.exe F:/code/test.py Traceback (most recent call last): File "F:/code/test.py", line 5, in <module> print "測試"+u"文本" UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
編碼解碼
#coding:utf8 u = u'苑' print repr(u) # u'\u82d1' # print str(u) #UnicodeEncodeError s = u.encode('utf8') print repr(s) #'\xe8\x8b\x91' print str(s) # 苑 u2 = s.decode('utf8') print repr(u2) # u'\u82d1'
str和unicode都是basestring的子類。嚴格意義上說,str實際上是字節串,它是unicode通過編碼後的字節組成的序列。對UTF-8編碼的str'苑'使用len()函數時,結果是3,由於utf8編碼的'苑' == '\xe8\x8b\x91';
而unicode是一個字符串,str是unicode這個字符串通過編碼(經過utf8或gbk編碼)後的字節組成的序列;
unicode纔是真正意義上的字符串,對字節串str使用正確的字符編碼進行解碼後得到,而且len(u'苑') == 1。
python3編碼
python3編碼
跟 Python2 相似,Python3 也有兩種數據類型:unicode和bytes。可是他們有不一樣的命名。在py3中,將unicode重命名爲str,將str重命名爲bytes。即python3中兩種數據類型是:str數據類型和bytes數據類型。str數據類型內存中是用unicode編碼方式存儲的,不能進行文件的存儲和傳輸;bytes數據類型在內存中是用utf8-八、utf8-1六、gbk、gb23十二、ascii等編碼方式存儲的,進行文件的存儲和傳輸須要轉化成bytes數據類型。
對於英文: str表現形式:s = 'alex' str在內存中的編碼方式:0101010101 unicode編碼方式 bytes表現形式:s = b'alex' bytes在內存中的編碼方式:0101010101 utf-8 gbk等編碼方式 例子 s = 'alex' s1 = b'alex' print(s,type(s)) //alex <class 'str'> print(s1,type(s1)) //b'alex' <class 'bytes'> 對於中文: str表現形式:s = '中國' str在內存中的編碼方式:0101010101 unicode編碼方式 bytes表現形式:s = b'\xe4\xb8\xad\xe5\x9b\xbd' bytes在內存中的編碼方式:0101010101 utf-8 gbk等編碼方式 例子 s = '中國' print(s,type(s)) //alex <class 'str'> s1 = b'中國' //這裏會報錯 print(s1,type(s1)) //b'alex' <class 'bytes'>
編碼解碼
編碼 encode:將str數據類型轉化成bytes數據類型;
解碼 decode:將bytes數據類型轉化成str數據類型。
編碼例子:
s1 = 'alex' s11 = s1.encode('utf-8') #將str轉換成utf-8 print(s11) # b'alex' s2 = '中國' s22 = s2.encode('utf-8') s33 = s2.encode('gbk') print(s22,type(s22)) # b'\xe4\xb8\xad\xe5\x9b\xbd' <class 'bytes'> print(s33,type(s33)) # b'\xd6\xd0\xb9\xfa' <class 'bytes'> #總結:utf-8一箇中文字符用3個字節,gbk一箇中文字符用2個字節表示
編碼實現
編碼實現
說到編碼,咱們須要在全局掌握這個工做過程,好比咱們在pycharm上編寫一個.py文件,從保存到運行數據究竟是怎麼轉換的呢?在解決這個問題以前,咱們須要解決一個問題:默認編碼,默認編碼其實就是你的解釋器解釋代碼時默認的編碼方式,在py2裏默認的編碼方式是ASCII,在py3裏則是utf8。(可使用sys.getdefaultencoding()查看默認的編碼方式):
#-*- coding: UTF-8 -*-
咱們在最開始只知道在py2裏若是不加上述這一句話,程序中有中文就會報錯,其實就是由於py2默認的ASCII碼,對於中文這些特殊字符沒法編碼。聲明這句話就是告訴python2.7解釋器解釋hello.py文件時使用utf8編碼,而不是使用默認的ASCII編碼方式,將文件編碼成字節串最後轉成0101的形式讓機器去執行;
hello.py文件保存時有本身特定的編碼方式,好比utf8,好比gbk。聲明使用的編碼方式必須與文件實際保存時使用的編碼方式一致,不然很大概率會出現代碼解析異常(即在.py文件中聲明解釋器編碼時使用utf8編碼方式,此時.py文件保存時也要使用utf8編碼方式保存至磁盤)。如今的IDE通常會自動處理這種狀況,改變聲明後同時換成聲明的編碼方式保存,但當使用操做系統上的文本編輯器編輯文本時須要當心,文件保存的編碼方式取決於你使用的編輯器默認的樣式(可調);
出現亂碼的狀況
案例1:
#!-*- coding:utf-8 -*- #__author: lriwu s = "特斯拉" print (s) F:\code>python test.py 特斯拉 #在cmd下使用python3編譯,能夠正常顯示。 正常顯示條件: 1. py文件是以utf8編碼方式存儲,解釋器也是以utf8編碼方式對.py文件進行編譯; 2.打印的內容要在終端顯示,在python3中字符串是str類型,在內存中是以unicode編碼方式存儲。因此cmd(windows默認使用gbk編碼)可以識別該unicode編碼,因此可以正常顯示。(unicode全部的編碼方式都能識別)
#!-*- coding:utf-8 -*- #__author: lriwu s = "特斯拉" print (s) F:\code>python2 test.py 鐗規柉鎷 #在cmd下使用python2編譯,不能正常顯示。 不能顯示緣由: 1. py文件是以utf8編碼方式,解釋器也是以utf8編碼方式對.py文件進行編譯。這個知足; 2.打印的內容要在終端顯示,在python2中字符串是str類型,在內存是以bytes編碼方式存儲(這裏是以utf8編碼方式存儲)。因此cmd(windows默認使用gbk編碼)不可以識別該utf8編碼,因此不能正常顯示。
實如今py2上正常顯示:
#!-*- coding:utf-8 -*- #__author: lriwu print (u'"特斯拉"') F:\code>python2 test.py "特斯拉"
案例2:
在py2中正常顯示
f = open('ces','r') print (f.read()) E:\soft_install\python\python2.7\python2.exe F:/code/test.py 測試 # open('ces','r')這個是調用操做系統命令執行,因此使用的是windows默認的gbk編碼。在py2中會自動的將gbk編碼後的bytes數據解碼成 unicode 字符串。
在py3上顯示亂碼
f = open('ces','r') print (f.read()) E:\soft_install\python\python2.7\python2.exe F:/code/test.py 嫺嬭瘯 #open('ces','r')這個是調用操做系統命令執行,因此使用的是windows默認的gbk編碼。gbk編碼後的bytes數據類型在pycharm中沒法經過utf8的方式進行解碼,因此顯示亂碼。
在py3上正常顯示
f = open('ces','r',encoding='utf8') print (f.read()) E:\soft_install\python\python3.5\python.exe F:/code/test.py 測試 #在這裏聲明windows打開文件時使用utf8方式編碼,而不是使用windows默認的gbk進行編碼。