整理python在檔案讀取時報錯和cpu執行時字串報錯unicodeencodeerror、unicodedecodeerror
解釋py2和py3字串資料型別,和bytes和unicode在py2和py3中的不同表現形式。
1.編碼和解碼
2.python 2中的字元編碼
3.python 3中的字元編碼
4.檔案從磁碟到記憶體的編碼
5.常見編碼問題
1.編碼和解碼
字元乙個資訊單位,它是各種文字和符號的統稱,比如乙個英文本母是乙個字元,乙個漢字是乙個字元,乙個標點符號也是乙個字元。
字元編碼(character encoding)是將字符集中的字元碼對映為位元組流的一種具體實現方案,常見的字元編碼有 ascii 編碼、utf-8 編碼、gbk 編碼等
編碼的過程是將字元轉換成位元組流,解碼的過程是將位元組流解析為字元。
2.python 2中的字元編碼
python 2 中字串型別有兩種,unicode型和str型,他們存的分別是unicode資料型別和位元組資料型別。str 型別的字串的編碼格式可以是 ascii、utf-8、gbk等任何一種型別。
無論是utf8還是gbk都只是一種編碼規則,一種把unicode資料編碼成位元組資料的規則,所以utf8編碼的位元組一定要用utf8的規則解碼,否則就會出現亂碼或者報錯的情況。
在字元編碼轉換操作時,遇到最多的問題就是 unicodeencodeerror 和 unicodedecodeerror 錯誤了,這些錯誤的根本原因在於 python2 預設是使用 ascii 編碼進行 decode 或者 encode 操作的。
str 型別與 unicode 型別的字串混合使用時,str 型別的字串會隱式地將 str 轉換成 unicode字串,如果 str字串是中文字元,那麼就會出現unicodedecodeerror 錯誤,因為 python2 缺省會使用 ascii 編碼來進行 decode 操作。
print
'苑昊'
# 苑昊
print
repr
(
'苑昊'
)
#'\xe8\x8b\x91\xe6\x98\x8a'
print
(u
"hello"
+
"yuan"
) #預設使用ascii編碼方式將"yuan"正確轉換成unicode型別,進行字串拼接。
#print (u'鄒周'+'最帥') # unicodedecodeerror解碼錯誤,py2將str轉換成unicode失敗
#unicodedecodeerror: 'ascii' codec can't decode byte 0xe6
print (u'鄒周'+'最帥'.decode("gbk")) #指定解碼格式,字串拼接完成
3.python 3中的字元編碼
py3也有兩種資料型別:str和bytes; str型別存unicode資料,bytse型別存bytes資料,與py2比只是換了一下名字而已。
python 3最重要的新特性大概要算是對文字和二進位制資料作了更為清晰的區分,不再會對bytes位元組串進行自動解碼。文字總是unicode,由str型別表示,二進位制資料則由bytes型別表示。python 3不會以任意隱式的方式混用str和bytes,正是這使得兩者的區分特別清晰。你不能拼接字串和位元組包,也無法在位元組包裡搜尋字串(反之亦然),也不能將字串傳入引數為位元組包的函式(反之亦然)。
#print('alvin'+u'yuan')#位元組串和unicode連線 py2:alvinyuan
print
(b
'alvin'
+
'yuan'
)
#位元組串和unicode連線 py3:報錯 can't concat bytes to str
注意:無論py2,還是py3,與明文直接對應的就是unicode資料,列印unicode資料就會顯示相應的明文(包括英文和中文)
注意:我們上面講的string編碼是在cpu執行程式時的儲存狀態,是另外乙個過程。
還原乙個py檔案從建立到執行的編碼過程:
檔案執行前:
當我們儲存hello.py的時候,hello.py檔案就以pycharm預設的編碼方式儲存到了磁碟;關閉檔案後再開啟,pycharm就再以預設的編碼方式對該檔案開啟後讀到的內容進行解碼,轉成unicode到記憶體我們就看到了我們的明文。
檔案執行中:
點選執行按鈕或者在命令列執行該檔案時,py直譯器這個軟體就會被呼叫,開啟檔案,然後解碼存在磁碟上的bytes資料成unicode資料,這個過程和編輯器是一樣的,不同的是直譯器會再將這些unicode資料翻譯成c**再轉成二進位制的資料流,最後通過控制作業系統呼叫cpu來執行這些二進位制資料,整個過程才算結束。
5.常見編碼問題
1 cmd下的亂碼問題
hello.py12
#coding:utf8
print
(
'苑昊'
)
檔案儲存時的編碼也為utf8。
思考:為什麼在ide下用2或3執行都沒問題,在cmd.exe下3正確,2亂碼呢?
我們在win下的終端即cmd.exe去執行,大家注意,cmd.exe本身也乙個軟體;當我們python2 hello.py時,python2直譯器(預設ascii編碼)去按宣告的utf8編碼檔案,而檔案又是utf8儲存的,所以沒問題;問題出在當我們print'苑昊'時,直譯器這邊正常執行,也不會報錯,只是print的內容會傳遞給cmd.exe用來顯示,而在py2裡這個內容就是utf8編碼的位元組資料,可這個軟體預設的編碼解碼方式是gbk,所以cmd.exe用gbk的解碼方式去解碼utf8自然會亂碼。
py3正確的原因是傳遞給cmd的是unicode資料,cmd.exe可以識別內容,所以顯示沒問題。
明白原理了,修改就有很多方式,比如:
1print
(u
'苑昊'
)
改成這樣後,cmd下用2也不會有問題了。
2 open()中的編碼問題
建立乙個hello文字,儲存成utf8:
苑昊,你最帥!同目錄下建立乙個index.py
f=open('hello')為什麼 在linux下,結果正常:苑昊,在win下,亂碼:鑻戞槉(py3直譯器)?print(f.read())
因為你的win的作業系統安裝時是預設的gbk編碼,而linux作業系統預設的是utf8編碼;
當執行open函式時,呼叫的是作業系統開啟檔案,作業系統用預設的gbk編碼去解碼utf8的檔案,自然亂碼。
解決辦法:
f=open('hello',encoding='utf8')如果你的檔案儲存的是gbk編碼,在win 下就不用指定encoding了。print(f.read())
另外,如果你的win上不需要指定給作業系統encoding='utf8',那就是你安裝時就是預設的utf8編碼或者已經通過命令修改成了utf8編碼
python字符集編碼深入理解
在python中和字串相關的型別,分別是str,unicode兩種不同的型別 basestring str unicode指令碼字元編碼 指指令碼檔案本身是用何種字元編碼的,預設情況python直譯器 直譯器就是執行python 程式的程式 認為指令碼是ascii碼 test.py print 你好...
python深入 Python的深入理解
處理檔案和目錄 python 3 帶有乙個模組叫做 os,代表 作業系統 operating system os 模組 包含非常多的函式用於獲取 和修改 本地目錄 檔案程序 環境變數等的資訊。python 盡最大的努力在所有支援的作業系統上提供乙個統一的api,這樣你就可以在保證程式能夠在任何的計算...
深入理解Python類
c 中,類有兩個關鍵的內建函式,建構函式和析構函式。在python中,其實也有類似的函式,他們就是 def init self pass def del self pass def enter self pass def exit self pass在物件建立時執行操作。在物件析構時執行操作。注意 ...