在使用Python2時,我們習慣於在文件開頭聲明編碼
# coding: utf-8
不然在文件中出現中文,運行時就會報錯 SyntaxError: Non-ASCII character... 之類,這是因為python2的文件編碼默認使用的ascii,ascii碼是不支持中文的。
如果在開頭聲明了編碼,文件編碼就會變為utf-8。
python執行過程的編解碼
python使用的unicode類型作為編碼的基礎類型,默認情況下,python在執行文件過程中的編解碼為 str-->unicode-->str,當我們在python開頭聲明utf-8編碼后,編解碼就變為了 str-->ascii-->str
舉個簡單例子,就可以驗證這個現象。
# coding:utf-8 s = "我要學Python" print(1, s)
從打印結果可以看出,我們沒有做任何處理,中文在執行過程就被處理成了ascii碼
encode&decode
在了解了Python執行過程的編碼轉換后,那我們自己如果轉換編碼該如何實現呢?這里就得使用兩個內置方法 encode編碼和decode解碼。
例如:
# coding:utf-8 s = "我要學Python" s.encode("utf-8") # 編碼 s.decode("utf-8") # 解碼
上面是方法的簡單運用,但是執行上面代碼,第3行就會出現編解碼過程中常見的一個報錯
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
簡單分析下,明明執行的encode方法,為什么會拋decode錯誤呢?這就要從上面介紹的python執行過程來分析了。
在執行encode方法編碼時,python先要解碼,而Python解碼默認用unicode格式,而文件開頭指定的編碼格式為ascii,這就導致編碼格式與解碼格式不一致,從而產生了報錯 ascii 不能解碼成 unicode。
要解決這個問題,只需要在編碼前,用utf-8格式解碼就可以了
s = "我要學Python" s.decode("utf-8").encode("utf-8") # 編碼 s.decode("utf-8") # 解碼
中文亂碼解決方法
在了解編解碼過程后,我們來解決實際遇到的問題:接口響應中文亂碼!
比如:在接口測試中,有些響應類似 "\u9875\u9762\u4e0d\u5b58\u5728" 的響應內容,看起來就像亂碼
注意看亂碼前面有個u ,這表示使用的unicode編碼字符。可用以下方法進行解碼:
# 直接在 unicode 字符串前加u ===> 使用Python機制自動解碼 s = u"\u9875\u9762\u4e0d\u5b58\u5728" print(s) # 打印:頁面不存在。因為字符串為unicode編碼格式,python在執行過程中,默認就是使用的unicode解碼,編解碼類型一致,就看到了中文打印內容 # 使用 decode 方法解碼成中文 ===> 主動解碼 s = "\u9875\u9762\u4e0d\u5b58\u5728" print(s.decode("unicode_escape"))
常見問題
格式化帶有中文的字符串報錯
格式拼接的字符串包含中文,會拋錯:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
# coding:utf-8 s = "\u9875\u9762\u4e0d\u5b58\u5728" # 拼接的字符串 不包含 中文字符===>正常 print("result: %s" % s.decode("unicode_escape")) # 拼接的字符串 包含 中文字符串===>異常 print("結果: %s" % s.decode("unicode_escape"))
問題分析:
解決方法:
統一編碼格式
# coding:utf-8 s = "\u9875\u9762\u4e0d\u5b58\u5728" # 方法1:將右邊變為 ascii 編碼 print("結果:%s" % s.decode("unicode_escape").encode("utf-8")) # 方法2:將左邊變為 unicode 編碼 print(u"結果:%s" % s.decode("unicode_escape"))
帶有中文的字符串反轉后亂碼
帶有中文的字符串使用列表反轉方式后亂碼,使用decode("utf-8") 解碼,報錯:UnicodeDecodeError: 'utf8' codec can't decode byte 0xa0 in position 0: invalid start byte
# coding:utf-8 s = "qta_baseline_test_勿刪"[::-1] print(s) print(s.decode("utf-8"))
問題分析:
中文被Python解析后,先轉換成ascii碼
當使用列表反轉方式后,實際把ascii反轉
這就導致了反轉后的亂碼無法被decode("utf-8")正常解碼
解決方法:
因為采用的utf-8編碼,所以先使用utf-8解碼,解碼后再反轉
# coding:utf-8 s = "qta_baseline_test_勿刪"[::-1] print(s) s = "qta_baseline_test_勿刪".decode("utf-8")[::-1] print(s) s = s.encode("utf-8") # 為了后續字符串能正常使用,建議在按原編碼方式編碼 print(s)