摘要:關于解決亂碼問題的終極解決方案有個特別好玩的現象,當我們為了編碼頭疼的時候,幾乎搜索到所有的文章都會先發一通牢騷。另外,關于的亂碼問題,又是一個新的較長篇章。
關于解決Python亂碼問題的終極解決方案 (TL;DR)
有個特別好玩的現象,當我們為了python編碼頭疼的時候,幾乎搜索到所有的文章都會先發一通牢騷。然后在無可奈何地寫解決思路(是解決思路不是方案)。這個問題真不是新手問題,即使是十幾年python老手也經常頭疼。中國外國都一樣??纯催@個python專家在PyCon大會上用半個多小時講解亂碼的視頻就了解了,他自己都給自己的來回encoding, decoding, encoding, decoding說暈了,臺下舉手他都拒絕回答,可想而知這個問題復雜性。
我認為,幾乎每個pythoner,都會有一段人生浪費在了編碼上。可以說這個問題,是如果你不徹徹底底解決,就永遠會崩潰的地步。翻看我曾經寫的數篇文章就知道了:
對Python 2.x的通宵抱怨
Python中文字符的理解:str()、repr()、print
Python里中文編碼的理解:unicode、utf-8、gbk
牢騷結束,下面是我又一次用了兩個整天才測試整理書寫完成的ipython notebook筆記。ipynb格式的筆記源文件在這里,當然有可能會鏈接失效,有喜歡ipython的live coding筆記的且想要用這個筆記測試編碼的,請聯系我。
首先,需要先要了解python的print大法如果python的print的特性都沒有了解的話,希望你不要貿然嘗試用print去調試測試亂碼編碼的問題。
這里的print厲害到讓你不高興的地步——它不管你塞過來的是什么格式什么編碼,字符串數組對象什么的的都一口氣全打印出來。
感覺好像很好,但其實是我們仔細研究編碼問題的最大阻礙。
因為你塞給print一個unicode它能打出中文,塞一個utf-8或iso8895給它,也一樣給你打印出原文。這樣以來,你看著它出現原文后,就欣喜若狂產生了一種勝利的錯覺。
所以我想在這里最先說清楚它:
也不是說這種時候一點都不能用,而是說你可以print別的什么東西,但是如果想看清某個變量本質的話,千萬不要用。
這個時候要用print repr(字符串) ,或者最好是在命令行或ipython里面測試,像這樣:
看出區別了嗎?明確了這點,再來繼續研究編碼問題。
簡單來說,先要記住,在Python2里字符串只有兩大陣營: unicode和str如果type(字符串)顯示結果是str,其實指的是bytes字節碼。
而其它各種我們所說的utf-8,gb2312等等也都是Unicode的不同實現方式。
這里不要去考慮那么復雜,只要先記住這兩大陣營就行。
絕對要記住的:
從unicode轉換到str,這個叫encoding,編碼。
從str轉換到unicode,這個叫decoding,解碼。
(圖片引用自知乎相關某答案。)
來回記住這個問題,才能進入下一步!
然后來看個案例。
通過上面兩種格式的對比我們看到,str和unicode的各種區別。
那么,既然變量里面會出現兩種不同的格式,如果我們把兩種格式的字符串連在一起操作會發生什么呢?
如下:
以上是我們用顯性字符串來比較兩種格式字符串的區別。
但是,我們經常性處理python編碼問題,都不是在這種顯性的字符串上出現的,不是從網上爬取的就是從本地文件讀取的,意思就是文件內容龐大,編碼格式很難猜到是什么。
所以這里我們將問題再拆分為兩部分討論:本地文件和網絡資源。
首先在本地建立一個有中文的以utf-8格式保存的文本文件(實際上無論.txt還是.md等都無所謂,內容是一樣的)。
內容只有"你好"。
上面看到,從文件讀取出來的,就是str格式的字符串。這種時候實際上是最迷糊也最容易造成之后錯誤的,就是分不清該編碼還是該解碼。
那么如果要把str轉化為unicode,就要解碼,也就是decoding.
所以上面提到,必須要記住這兩個區別。話說回來,我們該怎么統一他們呢?
那么如果現在我搞反了怎么辦?就會再次出現下面錯誤:
為了避免兩種格式的字符串在一起亂搞,統一他們是必須的。但是以哪一種為統一的呢,unicode還是bytes?
網上各種文章統一口徑,要求代碼中出現所有的變量都統一為unicode。
可是我在實踐和測試中都越來越發現:這種做法真的不那么可靠,甚至我懷疑有可能我們碰到那么多的問題,都是由它攪亂引起的。
這樣就明白了:除了r.text返回的內容外,其它幾乎都是使用str格式,也就是bytes字節碼碼。所以我們只要轉化requests相關的內容就行!
實際上,requests返回的response中, 除了用.text獲取內容,我們還可以用.content獲取同樣的內容,只不過是bytes格式。
那就正和我們意,不用再去轉化每一個地方的字符串,而只要盯緊這一個地方就足夠了。
為什么我們不能把所有字符串變量統一為unicode呢?先提醒下,變成unicode的過程,叫decoding。不要記錯。
像.text經常把ISO8859等猜不到也檢測不到編碼(機率很低)的字符串扔過來,如果遇到的話,是很麻煩的。
decoding有兩種方法:
unicode(b"你好‘) b"你好".decode("utf-8")
這里因為不知道來源的編碼,所以必須用unicode()來解碼,而不能用.decode("utf-8"),因為顯然你不能亂寫解碼名稱,如果來源果真是(很大幾率是)ISO8859等方式,那么錯誤的解碼肯定會產生亂碼,或者直接程序報錯。切記!
所以這里只能用unicode()解碼。如下例:
結論:一定記住,全文都統一用str格式字符串 只要盯緊requests、json等這種經常處理外來資源的庫就好了。只要控制好外來源的字符串,統一為str,其它一切都好說!
實際上,我發現遇到的絕大多數編碼問題,實際上不是python原生方法導致的,而是這些外來庫所引起的!因為每個模塊都會有自己的一套處理編碼的方式,你還真不知道它是采用哪個。就像JSON的dumps()一樣埋著大坑等著我們。所以真正應該盯緊的就是這些庫了。
下面是一個從獲取網絡資源(含中文且被requests認為編碼是ISO8850的網頁)到本地操作且存儲到本地文件的完整測試。
import requests r = requests.get("http://pycoders-weekly-chinese.readthedocs.io/en/latest/issue5/unipain.html") # write a webpage to local file with open("test.html", "w") as f: f.write( r.content ) # read from a local html file with open("test.html", "r") as f: ss = f.read()
大功告成!效果如下:
再也不用糾結、檢查每一個變量、寫一大堆嵌套轉化方法了!注意,只要盯緊各種外來模塊和庫的文字處理就夠了。另外,關于JSON的亂碼問題,又是一個新的較長篇章。我會單分一篇,請到我的專欄里找。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/41379.html
摘要:經常有讀者在公眾號上問亂碼的問題,昨天又有一個小伙伴問及此事,其實這個問題很簡單,但是想要說清楚卻并不容易,因為每個人亂碼的原因都不一樣,給每位小伙伴都把亂碼的原因講一遍也挺費時間的,因此,松哥今天決定寫一篇文章,和大伙好好捋捋中的亂碼問題 經常有讀者在公眾號上問 JavaWeb 亂碼的問題,昨天又有一個小伙伴問及此事,其實這個問題很簡單,但是想要說清楚卻并不容易,因為每個人亂碼的原因...
摘要:也是相關的,因為它們已經成為實現和使用的主要基準之一。在本文發表之后不久,和中有容易獲得的不同實現用于測試你所能想到的任何數據集。在這篇文章中,作者提出了對訓練的不同增強方案。在這種情況下,鑒別器僅用于指出哪些是值得匹配的統計信息。 本文不涉及的內容首先,你不會在本文中發現:復雜的技術說明代碼(盡管有為那些感興趣的人留的代碼鏈接)詳盡的研究清單(點擊這里進行查看 鏈接:http://suo....
摘要:注本文的原文地址為這個是性能快速優化的第二部分,第一部分請點擊這里。當你寫代碼了,過一遍數據結構,迭代結構,內建和為創建擴展,如有必要。更新是在的范圍之外,這意味著你可以使用這個標準庫來運行多個進程??聪挛业牡挠《妊葜v 注:本文的原文地址為 Quick Python Performance Optimization: Part II 這個是 Python 性能快速優化的第二部...
摘要:立即執行的驗證的參數是異步調用的驗證當在中通過調用使狀態穩定之后,不管調用多少次,值都不會再發生變化一諾千金的優點是什么我看了很多文章在介紹的時候都會提到回調噩夢。 showImg(https://segmentfault.com/img/remote/1460000006797059); TL;DR本文是對 Promise 一些概念點的歸納和對 Promise 在解決什么問題的思考。...
摘要:在環境下,徹底解決無法插入和顯示中文的問題下插入中文顯示亂碼解決方案回車輸入密碼進入查看狀態如下默認的是客戶端和服務器都用了,所以會亂碼。解決方案上文提到了用臨時方法更改數據庫的字符集設置,顯示中文,但是后來發現在有的系統下并不能成功。在debian環境下,徹底解決mysql無法插入和顯示中文的問題Linux下Mysql插入中文顯示亂碼解決方案mysql -uroot -p 回車輸入密碼進入...
閱讀 1819·2021-11-24 09:39
閱讀 2297·2021-09-30 09:47
閱讀 4166·2021-09-22 15:57
閱讀 1886·2019-08-29 18:36
閱讀 3586·2019-08-29 12:21
閱讀 598·2019-08-29 12:17
閱讀 1273·2019-08-29 11:25
閱讀 732·2019-08-28 18:26