python基礎篇10-py2和py3編碼

編碼基礎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進行編碼。
複製代碼
相關文章
相關標籤/搜索