距離上一篇的python --- 字符編碼學習小結(一)已通過去2年了,2年的時間裏,確實也遇到了各類各樣的字符編碼問題,也能解決,可是每次都是把全部的方法都試一遍,而後終於正常。這種方法顯然是不科學的,本質上不理解問題產生的緣由,因此遇到問題,只能先用萬能鑰匙,不行的話再逐個換。2年的時間積累和學習目前對此的瞭解又深入了一點。html
1、常見的編解碼問題:python
先來講幾個常見的問題吧。ubuntu
這2個問題,都是最最多見,又最基本典型的問題,又最基本的2個問題,從這2個問題出發,弄清楚問題產生的緣由,後面不少問題基本都是組合場景,能比較輕鬆解決。windows
二:問題產生緣由分析post
一、根本緣由:學習
二、分析問題1產生緣由和解決方法:編碼
第一步: ***格式的txt文件被讀取到內存中 第二步:顯示器按&&&方式來讀取? 當&&& 與 ***不一致就會亂碼,分析以下: A: 正常默認狀況下,python解析器嘗試使用 &&& = GBK格式(windows默認格式:CP396->GBK)來解析這塊內存數據來顯示: a : 若是讀取的文件是*** = GBK格式,ok,不亂碼 b : 若是讀取的文件是*** = UTF-8格式就會產生亂碼。由於以UTF-8形式表示的編碼在GBK編碼中被解釋成其餘字符串致使產生亂碼 B: 而若是此時在在pycharm裏能夠經過設置settings的encoding格式=UTF-8來解析這塊內存數據: a: 若是讀取的文件是GBK格式會產生亂碼。由於以GBK形式表示的編碼在utf-8編碼中被解釋成其餘字符串致使產生亂碼 b : 若是讀取的文件是UTF-8格式就不會亂碼。 A.b 解決辦法:.decode('utf-8').encode('gbk')或者decode('utf-8') B.a 解決辦法:decode('gbk').encode('utf-8')或者decode('gbk')
其中,windows默認的解析格式是GBK,在pycharm裏能夠經過設置settings的encoding格式來設置;而文件保存格式,在notepad++能夠選擇
讀取文件推薦使用方法:
推薦使用codecs模塊,使用codecs/io.open()顯示指定文件編碼格式。python 2 open(filename,mode),不支持encoding參數,但python 3支持
三、分析問題2產生緣由和解決方法:spa
第一步: 以***編碼格式保存py文件。 第二步:顯示器按&&&方式來讀取? 在解析過程當中,當字符在***沒法找到時程序會拋異常,分析以下: A: 正常默認狀況下,python的默認編碼是 *** = ASCII編碼: a : 默認狀況下,python解析器嘗試使用 &&& = GBK 來解析數據,可是中文並非ASCII字符,致使解釋器不知如何處理,拋異常. b : 設置pycharm的settings的encoding格式 = UTF-8, 來解析數據,可是中文並非ASCII字符,致使解釋器不知如何處理,拋異常. 解決方法:聲明源文件的編碼方式。 推薦方法:#coding=utf-8
3、其餘常見不一樣類型問題3d
一、不可見字符BOM致使解析異常code
二、chardet檢測字節流編碼格式,是基於機率,存在不許確的問題。字節編碼沒法準確猜對,必須明確告知
三、os.walk() 遍歷含中文的路徑時中文亂碼報錯
如今須要遍歷E:/ 下的路徑,部分以下所示,存在中文文件名
A: 報錯代碼段以下:讀取的
#!/usr/bin/python
# -*- coding: UTF-8 -*- import os for root, dirs, files in os.walk("E:/", topdown=False): for name in files: print(os.path.join(root, name))
讀取結果以下:
B: 致使取讀錯誤的緣由以下:
os.walk(folder_name) 返回的文件路徑編碼和入參folder_name編碼有關:
• 當folder_name是unicode時,os.walk返回的root,directories, filenames也是unicode
• 不然按照sys.getfilesystemencoding()編碼返回str.中文windows 系統sys.getfilesystemencoding()返回「mbcs」(即:「gbk」)英文ubuntu系統sys.getfilesystemencoding()返回「utf-8」
若是根路徑中有中文,路徑須要使用unicode編碼做爲os.walk的入參
C : 修改代碼以下,能正常讀取中文路徑
for root, dirs, files in os.walk(u"E:/", topdown=False): 或者 for root, dirs, files in os.walk("E:/".decode('utf-8'), topdown=False):