Python字串開頭的b"、u"、r"與中文亂碼
ofollow,noindex">智慧決策上手系列教程索引
先看幾個常見的中文亂碼:
s = u'More更多請關注我' print('--encoded---') print('【utf-8】', bytes(s, encoding='utf-8')) print('【utf-16】', bytes(s, encoding='utf-16')) print('【gbk】', bytes(s, encoding='gb2312')) print('【unicode-escape】', bytes(s, encoding='unicode-escape')) print('--decoded--') print('【utf-8=>utf-8】', s.encode('utf-8').decode('utf-8')) print('【utf-8=>utf-16】', s.encode('utf-8').decode('utf-16')) print('【utf-8=>ISO-8859-1】', s.encode('utf-8').decode('ISO-8859-1')) print('【gbk=>ISO-8859-1】', s.encode('gbk').decode('ISO-8859-1'))
執行得到:

image.png
仔細看一下,找到下面兩個規律:
- 要麼是上面encode編碼後的
\...\...\...
,要麼是錯誤解碼decode之後的亂碼。 - 除了兩個最後輸出
utf-16
的,其他的都能正常顯示英文More
。
u'和b'
第一行我們用了 u'More...'
,這個u是可以省略的,在python3裡面所有字串預設都是 utf-8
編碼解碼的,這個u就是指示要用 utf-8
編碼,所以可省略。
上面四個encoded輸出的開頭都有 b'...'
開頭,因為程式碼裡面是 bytes(s,...)
,bytes是位元組,字串可以用很多種編碼方式變為位元組,就像密碼電報一樣,同一個資訊可以用不同的演算法加密成各種不同的亂碼,如果你不知道是什麼編碼的,你就讀不出。
python2中只有位元組形式的字串,沒有u'開頭的utf-8編碼的,所以python3才發明了b'開頭這種表示位元組的方法,相容舊版本。
字串經過特定的方式編碼coding成為位元組,然後再通過正確的方式也可以把位元組還原為字串。關鍵就是要知道原來的編碼方式
.encode('utf-8').decode('utf-8')
這句當然看起來沒毛病,所以也輸出了正確的文字。
而後面 s.encode('utf-8').decode('utf-16')
這種就不正常了,編碼encode方式和decode解碼方式不一樣,就導致了亂碼。
解決亂碼問題
首先要想辦法知道或者實驗出原來是什麼編碼的,你可以對照上面輸出的程式碼進行猜測。
如果是很多斜槓的bytes,那麼就直接嘗試不同的decode:
s=b'More\xe6\x9b\xb4\xe5\xa4\x9a\xe8\xaf\xb7\xe5\x85\xb3\xe6\xb3\xa8\xe6\x88\x91' print(s.decode('utf-8'))
如果是被錯誤解碼的亂碼,那麼就嘗試反向encode再decode就能還原:
#亂碼來自s.encode('gbk').decode('ISO-8859-1') s='More¸ü¶àÇë¹Ø×¢ÎÒ'.encode('ISO-8859-1').decode('gbk') print(s)
r' 強制不轉義
先看下這個問題:
s1=r'.\folder\new.file' s2=b'.\folder\new.file' s3=u'.\folder\new.file' print('r:',s1) print('b:',s2) print('u:',s3)
它的輸出是這樣的,你肯定猜不到:

image.png
為什麼會是這樣?只有r開頭的正常。
我們都知道程式碼裡面字串要用引號包裹,那麼字串裡面要是也有引號怎麼辦?換行怎麼辦?
程式語言會用特殊方法來表示這些特殊符號,叫做轉義字元。比如 \n
表示回車換行, \f
表示換頁, \"
表示雙引號, \'
標示單引號...
那麼真的遇到了 \n
怎麼辦?就像上面那個情況,b'把f編碼成了\x0,而u'直接把 \f
弄沒了, \n
變成了回車...
為了避免這種情況,就有了r'強制不轉義,優點是明顯的,不會亂變,缺點也是有的,那就不能真的顯示回車換行了啊。
一般在目錄地址和正則表示式中我們常用r'避免混亂。
智慧決策上手系列教程索引
每個人的智慧決策新時代
如果您發現文章錯誤,請不吝留言指正;
如果您覺得有用,請點喜歡;
如果您覺得很有用,歡迎轉載~
END