python3 字符集編碼以及python3 亂碼問題
python3 字元編碼
編碼
為什麼有編碼
計算機只能處理數字,人類需要處理大量的文字,如果要計算機處理文字,就必須把文字轉換為數字,才可以進行處理。
編碼可以理解為編碼表,每個字母或漢字對應一個二進位制或十進位制的編號。在將文字文件的文字(漢字、韓語、日文等等語言)轉化為計算機可以理解的數字的時候,去表格裡面找這些數字,方便計算機理解。比如:
字母A用ASCII編碼是十進位制的65,二進位制的01000001
字元0用ASCII編碼是十進位制的48,二進位制的00110000,
ASCII 編碼
計算機是美國人發明的,所以,最早只有 127 個大小寫字母、數字和一些符號進入了編碼體系,這套編碼就是 ASCII 碼。比如:
大寫字母 A 的編碼是 65,小寫字母 z 的編碼是 122。
ASCII 編碼的侷限性是該編碼只解決了將英語轉化為計算機能理解的語言的問題,對於中文、日文、韓文、等等其他語言的轉換,會出現亂碼,為了解決亂碼的國際問題,有了 Unicode 編碼
Unicode 編碼
Unicode 編碼把所有語言都統一到一套編碼裡面,這樣就不會有亂碼的問題了。python3 內部使用的就是 unicode 編碼
但是隨之而來的新問題是,Unicode 編碼比 ASCII 編碼需要多一倍的儲存空間(原理在此不闡述,我也不懂,有興趣可以問問度娘),那麼在儲存和傳輸上面就不划算,為了解決這個問題,又將 Unicode 編碼轉化為 UTF-8 編碼。
UTF-8 編碼
因為解決了大部分語言編碼的問題,又被稱為萬國碼。
能將各個國家的各種語言隨意轉換。
GBK 編碼
GBK全稱《漢字內碼擴充套件規範》,屬於國家標準,
GBK 和 UTF-8 的主要區別:
GBK 包含全部中文字元
UTF-8 包含全世界所有國家需要用到的字元。
GBK是在國家標準GB2312基礎上擴容後相容GB2312的標準(我是沒看懂,你們隨意)
UTF-8編碼的文字可以在各國各種支援UTF8字符集的瀏覽器上顯示。
如果是UTF8編碼,則在外國人的英文IE上也能顯示中文,而無需他們下載IE的中文語言支援包。
所以,對於英文比較多的論壇 ,使用GBK則每個字元佔用2個位元組,而使用UTF-8英文卻只佔1個位元組。
UTF8是國際編碼,它的通用性比較好,外國人也可以瀏覽論壇,GBK是國家編碼,通用性比UTF8差,不過UTF8佔用的資料庫比GBK大。
編碼工作方式
計算機記憶體中,統一使用Unicode編碼
,你在 .py 或者 .txt 鍵入文字的時候,計算機記憶體是以 Unicode 編碼的方式對這些文字進行儲存的。
編輯完成之後,儲存的時候,再把 Unicode 編碼轉化為 UTF-8 儲存的檔案中。
另外流量網頁的時候,伺服器會把動態生成的 Unicode 內容,轉化為 UTF-8 編碼形式,再傳輸到瀏覽器,那麼使用者就可以看到自己能理解的語言組成的網頁,比如中文、日文、韓文等等。很多網頁的原始碼上會有類似<meta charset='UTF-8' /> 的資訊,表示該網頁是 UTF-8 編碼
python3 編碼
python3 使用的是 Unicode 編碼方式,也就意味著,python3 字串支援多語言。
雖然 python3 字串型別在記憶體中以 Unicode 表示,但是在網路上傳輸或者儲存到磁碟的時候,需要把 str 變為以位元組為單位的 bytes。
encode() 方法
encode 方法以指定的編碼格式編碼字串。返回編碼後的字串,是一個 bytes 物件
。
str.encode(encoding='UTF-8',errors='strict')
- encoding: 需要使用的編碼,如 UTF-8,GBK
- errors:可選引數,預設 strict,表示如果發生編碼錯誤,返回一個 UnicodeError。
decode() 方法
decode 方法以指定的編碼格式解碼 bytes 物件,預設 UTF-8 編碼,該方法返回解碼後的字串。
bytes.decode(encoding='UTF-8',errors='strict')
- encoding:要使用的編碼,UTF-8,GBK
- error:可選引數,瞭解即可,預設 strict,可不寫。
str = '阿銘python'
str_utf8 = str.encode('UTF-8')
str_gbk = str.encode('GBK')
print(str)
print('str 物件型別:', type(str))
print('\r')
print('UTF-8 編碼:', str_utf8)
print('str_utf-8 物件型別:', type(str_utf8))
print('\r')
print('GBK 編碼: ', str_gbk)
print('str_gbk 物件型別:', type(str_gbk))
print('\r')
print('UTF-8 解碼:', str_utf8.decode('UTF-8', 'strict'))
print('GBK 解碼: ', str_gbk.decode('GBK', 'strict'))
結果如下:
阿銘python
str 物件型別: <class 'str'>
UTF-8 編碼: b'\xe9\x98\xbf\xe9\x93\xadpython'
str_utf-8 物件型別: <class 'bytes'>
GBK 編碼: b'\xb0\xa2\xc3\xfapython'
str_gbk 物件型別: <class 'bytes'>
UTF-8 解碼: 阿銘python
GBK 解碼: 阿銘python
這些亂碼有沒有看起來很熟悉!!!!!!所以下次看到的時候,可以說這些不是亂碼,是 UTF-8 和 GBK 編碼的 bytes 物件。(我其實不知道我想表達什麼 - -#)
python3 亂碼
python3 內部使用 unicode 編碼,外部面對各種各樣亂七八糟的編碼,中國最常用的是 gbk 和 utf-8。
在編輯 .py 的時候,python 預設會任務原始碼檔案是 ASCII 編碼。如果程式碼只涉及的英文,那麼轉換沒有問題,如果涉及到其他語言,比如中文,就會丟擲異常。
解決方法很簡單,在原始碼檔案的前兩行指定編碼格式,網上有說一定放在前兩行,放在第三行都不起作用。
# -*- coding: utf-8 -*-
window 問題
如果在 window 控制檯執行程式碼,雖然程式執行了,但是螢幕上列印的不是中文,原因是 python 編碼於控制檯編碼不一致。
Windows 控制檯使用的是 gbk
,而程式碼中使用的 utf-8,編碼和解碼的方式不一致,那麼就不能正常的顯示。
解決方法是將原始碼檔案修改為:
# -*- coding: gbk -*-
或者另外一種方式,保持原始碼檔案 utf-8 格式不變,在中文字串前面新增 u 字母,表示後面的字串以 unicode 格式儲存。
a = '大師兄'
b = u'大師兄'
print(a, type(a))
print(b, type(b))
字元前面加 u 表明這是一個 unicode 物件,這個字會以 unicode 格式存在於記憶體中,而如果不加u 表明這僅僅是一個使用某種編碼的字串,編碼格式取決於 python 對原始碼檔案編碼的識別。
Python 在向控制檯輸出 unicode 物件的時候會自動根據輸出環境的編碼進行轉換,但如果輸出的不是 unicode 物件而是普通字串,則會直接按照字串的編碼輸出字串,從而出現亂碼的現象。
encode 和 decode 方法
decode函式也可以將一個普通字串轉換為unicode物件。
decode 將普通字串按照引數中的編碼格式進行解析,然後生成對應的 unicode 物件。
那麼encode正好就是相反的功能,是將一個unicode物件轉換為引數中編碼格式的普通字元。
isinstance()
判斷字串是否是 unicode 的方法,python2 和 python3 略有不同,但是使用的都是 isinstance 方法。
# python2
isinstance(str, unicode)
# python3
isinstance(str, str)
另外補充一個獲取系統預設編碼的方法
import sys
print(sys.getdefaultencoding())