新聞資訊  快訊  焦點  財經  政策  社會
互 聯 網   電商  金融  數據  計算  技巧
生活百科  科技  職場  健康  法律  汽車
手機百科  知識  軟件  修理  測評  微信
軟件技術  應用  系統  圖像  視頻  經驗
硬件技術  知識  技術  測評  選購  維修
網絡技術  硬件  軟件  設置  安全  技術
程序開發  語言  移動  數據  開源  百科
安全防護  資訊  黑客  木馬  病毒  移動
站長技術  搜索  SEO  推廣  媒體  移動
財經百科  股票  知識  理財  財務  金融
教育考試  育兒  小學  高考  考研  留學
您當前的位置:首頁 > IT百科 > 程序開發 > 語言 > Python

帶你徹底搞明白python3編碼原理

時間:2019-11-22 14:38:54  來源:  作者:

在之前的文章中,我們介紹過編碼格式的發展史。今天我們通過幾個例子,來徹底搞清楚Python3中的編碼格式原理,這樣你之后寫python腳本時碰到編碼問題,才能有章可循。

 

我們先搞清楚幾個概念:

  • 系統默認編碼:指python解釋器默認的編碼格式,在python文件頭部沒有聲明其他編碼格式時,python3默認的編碼格式是utf-8。
  • 本地默認編碼:操作系統默認的編碼,常見的windows的默認編碼是gbk,linux的默認編碼是UTF-8。
  • python文件頭部聲明編碼格式:修改的是文件的默認編碼格式,只是會影響python解釋器讀取python文件時的編碼格式,并不會改變系統默認編碼和本地默認編碼。

通過python自帶的庫,可以查看系統默認編碼和本地默認編碼

CopyPython 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
>>> import locale
>>> locale.getdefaultlocale()
('zh_CN', 'cp936')
>>>

注意,因為我在windows系統的電腦上 進行測試,所以系統默認編碼返回“cp936”, 這是代碼頁(是字符編碼集的別名),而936對應的就是gbk。如果你在linux或者mac上執行上面的代碼,應該會返回utf-8編碼。

其實總結來看,容易出現亂碼的場景,基本都與讀寫程序有關,比如:讀取/寫入某個文件,或者從網絡流中讀取數據等,因為這個過程中涉及到了編碼 和解碼的過程,只要編碼和解碼的編碼格式對應不上,就容易出現亂碼。下面我們舉兩個具體的例子,來驗證下python的編碼原理,幫助你理解這個過程。注意:下面的例子都是在pycharm中寫的。

01默認的編碼格式#

我們新建一個encode_demo.py的文件,其文件默認的編碼格式是UTF-8(可以從pycharm右下角看到編碼格式),代碼如下:

Copy"""
 @author: asus
 @time: 2019/11/21
 @function: 驗證編碼格式
"""
import sys, locale


def write_str_default_encode():
 s = "我是一個str"
 print(s)
 print(type(s))
 print(sys.getdefaultencoding())
 print(locale.getdefaultlocale())

 with open("utf_file", "w", encoding="utf-8") as f:
 f.write(s)
 with open("gbk_file", "w", encoding="gbk") as f:
 f.write(s)
 with open("jis_file", "w", encoding="shift-jis") as f:
 f.write(s)


if __name__ == '__main__':
 write_str_default_encode()

我們先來猜測下結果,因為我們沒有聲明編碼格式,所以python解釋器默認用UTF-8去解碼文件,因為文件默認編碼格式就是UTF-8,所以字符串s可以正常打印。同時以UTF-8編碼格式寫文件不會出現亂碼,而以gbk和shift-jis(日文編碼)寫文件會出現亂碼(這里說明一點,我是用pycharm直接打開生成的文件查看的,編輯器默認編碼是UTF-8,如果在windows上用記事本打開則其默認編碼跟隨系統是GBK,gbk_file和utf_file均不會出現亂碼,只有jis_file是亂碼),我們運行看下結果:

Copy# 運行結果
我是一個str
<class 'str'>
utf-8
('zh_CN', 'cp936')

# 寫文件utf_file、gbk_file、jis_file文件內容分別是:
我是一個str
???????str
????str

和我們猜測的結果一致,下面我們做個改變,在文件頭部聲明個編碼格式,再來看看效果。

02 python頭文件聲明編碼格式#

因為上面文件encode_demo.py的格式是UTF-8,那么我們就將其變為gbk編碼。同樣的我們先來推測下結果,在pycharm中,在python文件頭部聲明編碼為gbk后(頭部加上 # coding=gbk ),文件的編碼格式變成gbk,同時python解釋器會用gbk去解碼encode_demo.py文件,所以運行結果應該和用UTF-8編碼時一樣。運行結果如下:

Copy# 運行結果
我是一個str
<class 'str'>
utf-8
('zh_CN', 'cp936')

# 寫文件utf_file、gbk_file、jis_file文件內容分別是:
我是一個str
???????str
????str

結果確實是一樣的,證明我們推論是正確的。接下來我們再做個嘗試,假如我們將(# coding=gbk)去掉(需要注意,在pycharm中將 # coding=gbk去掉,并不會改變文件的編碼格式,也就是說encode_demo.py還是gbk編碼),我們再運行一次看結果:

Copy File "D:/codespace/python/pythonObject/pythonSample/basic/encodeDemo/encode_demo.py", line 4
SyntaxError: Non-UTF-8 code starting with '\xd1' in file D:/codespace/python/pythonObject/pythonSample/basic/encodeDemo/encode_demo.py on line 5, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

運行直接報錯了,我們加個斷點,看看具體的異常信息:

帶你徹底搞明白python3編碼原理

 

看錯誤提示是UnicodeDecodeError,python解釋器在對encode_demo.py文件解碼時,使用默認的UTF-8編碼,但是文件本身是gbk編碼,所以當碰到有中文沒辦法識別時,就拋出DecodeError。

03 敲黑板,劃重點#

python3中的str和bytes#

python3的重要特性之一就是對字符串和二進制流做了嚴格的區分,我們聲明的字符串都是str類型,不過Str和bytes是可以相互轉換的:

Copydef str_transfor_bytes():
 s = '我是一個測試Str'
 print(type(s))
 # str 轉bytes
 b = s.encode()
 print(b)
 print(type(b))
 # bytes轉str
 c = b.decode('utf-8')
 print(c)
 print(type(c))


if __name__ == '__main__':
 str_transfor_bytes()

需要注意一點:在調用encode()和decode()方法時,如果不傳參數,則會使用python解釋器默認的編碼格式UTF-8(如果不在python頭文件聲明編碼格式)。但是如果傳參的話,encode和decode使用的編碼格式要能對應上。

python3默認編碼是UTF-8?還是Unicode?#

經常在很多文章里看到,python3的默認編碼格式是Unicode,但是我在本文中卻一直在說python3的默認編碼格式是UTF-8,那么哪種說法是正確的呢?其實兩種說法都對,主要得搞清楚Unicode和UTF-8的區別(之前文章有提到):

  • Unicode是一個字符集,說白了就是把各種編碼的映射關系全都整合起來,不過它是不可變長的,全部都以兩個字節或四個字節來表示,占用的內存空間比較大。
  • UTF-8是Unicode的一種實現方式,主要對 Unicode 碼的數據進行轉換,方便存儲和網絡傳輸 。它是可變長編碼,比如對于英文字母,它使用一個字節就可以表示。

在python3內存中使用的字符串全都是Unicode碼,當python解釋器解析python文件時,默認使用UTF-8編碼。

open()方法默認使用本地編碼#

在上面的例子中,我們往磁盤寫入文件時,都指定了編碼格式。如果不指定編碼格式,那么默認將使用操作系統本地默認的編碼格式,比如:Linux默認是UTF-8,windows默認是GBK。其實這也好理解,因為和磁盤交互,肯定要考慮操作系統的編碼格式。這有區別于encode()和decode()使用的是python解釋器的默認編碼格式,千萬別搞混淆了。

總結#

不知道你看完上面的例子后,是否已經徹底理解了python3的編碼原理。不過所有的編碼問題,都逃不過“編碼”和“解碼”兩個過程,當你碰到編碼問題時,先確定源文件使用的編碼,再確定目標文件需要的編碼格式,只要能匹配,一般就可以解決編碼的問題。

最后,小編想說:我是一名python開發工程師,整理了一套最新的python系統學習教程,想要這些資



Tags:python 編碼   點擊:()  評論:()
聲明:本站部分內容來自互聯網,內容觀點僅代表作者本人,如有任何版權侵犯請與我們聯系,我們將立即刪除。
▌相關評論
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
▌相關推薦
在之前的文章中,我們介紹過編碼格式的發展史。今天我們通過幾個例子,來徹底搞清楚python3中的編碼格式原理,這樣你之后寫python腳本時碰到編碼問題,才能有章可循。 我們先搞清楚...【詳細內容】
2019-11-22   python 編碼  點擊:(2)  評論:(0)  加入收藏
最新更新
欄目熱門
欄目頭條
31选7开奖11185