[轉(zhuǎn)]Python 2.x中常見字符編碼和解碼方面的錯誤及其解決辦法

本文轉(zhuǎn)自:http://www.crifan.com/crifan_released_all/books/

Python 2.x中的字符編碼骡和,設(shè)計(jì)的的確不好剪返,導(dǎo)致初學(xué)者翰灾,甚至是即使用Python很長時間的人认轨,都會經(jīng)常遇到字符編解碼方面的錯誤嫁佳。

下面就把一些常見情璃诀,盡量的都整理出來弧可,并給出相應(yīng)的解決辦法。

看此文之前

Python中字符編碼所涉及的背后邏輯(從你輸入字符劣欢,到終端顯示字符的背后過程)

在去了解Python編碼解碼之前棕诵,還有個更加重要,但是很多時候卻被其他解釋相關(guān)知識的人所忽略的問題凿将,那就是:

對于Python中字符串校套,輸入輸出的背后邏輯。

即牧抵,知其所以然笛匙。

此處就簡單介紹一下,在Python中犀变,從你所輸入的字符串妹孙,到顯示出字符串,這背后的過程是什么樣的获枝。

只有了解了這個大概的過程蠢正,和背后的邏輯,你才能真正理解后面的所解釋的省店,字符串編碼解碼方面的錯誤嚣崭,以及如何解決這樣的錯誤。

對于你

你只是看到的是:

  • 你輸入了字符串
    • 不論是從Python的IDLE中輸入的
    • 還是寫入到Python文件中的
  • 然后你去運(yùn)行的對應(yīng)代碼懦傍,該P(yáng)ython代碼雹舀,經(jīng)過Python系統(tǒng),(此處及之后粗俱,我稱其為Python解析器)葱跋,的處理
  • 使得你可以看到最終所輸出的字符串
    • 不論是在Python的IDLE中看到的
    • 還是在windows的cmd中看到的。

對于Python解析器

而Python解析器所干的事情,就是:

Python解析器娱俺,根據(jù)當(dāng)前的所用的字符串編碼類型

  • 此字符串編碼類型稍味,是你自己所設(shè)置的

    • 不論是在Python的IDLE中,還是Python文件中
    • 都是你自己顯示指定對應(yīng)的編碼類型的
  • 當(dāng)然你沒顯示的指定的話荠卷,那就用默認(rèn)的配置

  • 如果是Python的IDLE模庐,如果你沒修改defaultencoding,那么就使用默認(rèn)的字符編碼

  • 可以通過sys.getdefaultencoding()而獲得油宜,比如此處獲得是:ascii
    此處插入圖片

  • ascii
  • 如果是Python文件掂碱,如果你沒聲明文件編碼,則使用默認(rèn)的編碼:UTF-8

  • 常見的做法是指定為對應(yīng)的UTF-8類型:# -- coding: utf-8 --

    • 相關(guān)內(nèi)容慎冤,不了解的可參考:【整理】關(guān)于Python腳本開頭兩行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用 – 指定文件編碼類型
  • 去執(zhí)行你的Python代碼

  • 其中疼燥,很常見的幾種動作是:

  • 打印print對應(yīng)的所獲得的字符

  • 對于字符串打印,Python的邏輯:

  • 如果是Unicode字符串,則可以,自動地,編碼為對應(yīng)的終端所用編碼,然后正確的顯示出來

  • 比如unicode的字符串,輸出到windows的默認(rèn)編碼為GBK的cmd中,則Python可以自動將Unicode編碼為GBK,然后輸出到cmd中

  • 個別特殊情況,也會出錯:

    • 當(dāng)此unicode字符串中包含某特殊字符,而目標(biāo)終端的編碼集合中,沒有此字符,則很明顯也是無法實(shí)現(xiàn)將Unicode編碼為對應(yīng)的特定編碼的字符串,無法正確顯示的
  • 如果是某種編碼類型的str,則需要該str的編碼類型,和目標(biāo)終端編碼匹配
    比如GBK的字符串,輸出到windows的默認(rèn)編碼為GBK的cmd,則是可以正常輸出的

  • 此處后來經(jīng)過代碼測試,就發(fā)現(xiàn)一個有趣或者說詭異的問題蚁堤,雖然我們python文件聲明的UTF-8編碼醉者,但是實(shí)際上實(shí)際上是用GBK編碼,而此時披诗,文件中的字符串撬即,很明顯是用GBK存儲的,所以呈队,將此GBK字符剥槐,輸出到GBK的cmd中,是可以正常輸出的宪摧。即粒竖,此處字符串的類型,很明顯只和文件所用的實(shí)際編碼有關(guān)几于,而和文件所聲明的代碼無關(guān)温圆。

  • 如果是UTF-8的字符串,輸出到windows的默認(rèn)編碼為GBK的cmd,就會出錯

  • 對相應(yīng)的字符,進(jìn)行編碼(為某種特定類型的字符str)孩革,或解碼(為對應(yīng)的unicode類型的字符)

  • 比如將當(dāng)前的某種編碼的字符串岁歉,解碼為Unicode字符串

  • 很明顯,也是要保證膝蜈,你字符串本身的編碼和所指定的編碼锅移,兩者之間要一致的

  • 比如:decodedUnicode = someUtf8Str.decode("UTF-8")

  • 而如果用這樣的:decodedUnicode = someGbkStr.decode("UTF-8"),那就會出現(xiàn)錯誤

所以你要

  • 確保當(dāng)前輸入的字符串的編碼饱搏,和對應(yīng)的編碼設(shè)置一致非剃,才能使得解析器正常解析你的字符串
  • 確保輸出字符串時,所用字符(的編碼)和目標(biāo)輸出所用的編碼一致推沸,才能正常在輸出終端顯示
  • 確保字符串本身的編碼备绽,和你去解碼等操作所用的編碼一致券坞,否則很明顯會由于編碼不一致而無法進(jìn)行解碼(等操作)

常見錯誤簡介

很明顯,如果你不遵守上述規(guī)則肺素,出現(xiàn)前面編碼不一致的情況恨锚,那么就會出現(xiàn)一些常見的編碼解碼方面的錯誤了夕凝。

此處只是簡單舉例如下:

  • 你python文件本身是GBK的蟆炊,對應(yīng)的字符串也是GBK的,然后你指定按照UTF-8解碼為對應(yīng)的Unicode螟深,那么當(dāng)然會導(dǎo)致人家Python解析器塌西,按照UTF-8編碼的方式他挎,去解析你的,實(shí)際上是GBK的字符捡需,當(dāng)然會出錯办桨,無法解析了。
  • 你所要打印的字符站辉,本身是UTF-8的呢撞,但是要打印輸出的終端是,windows的cmd庵寞,其默認(rèn)編碼為GBK,即將UTF-8的字符薛匪,顯示到GBK編碼的cmd中捐川,當(dāng)然也會出現(xiàn)錯誤了
  • 你所要打印出來的字符,雖然是unicode逸尖,但是其中包含了某些特殊字符古沥,而對應(yīng)的特殊字符在終端所用的編碼中不存在,比如將含某些特殊字符的Unicode字符串娇跟,打印到windows的默認(rèn)編碼為GBK的cmd中岩齿,而GBK編碼集合中,本身就沒有這些字符苞俘,所以盹沈,當(dāng)然也是無法顯示,會出現(xiàn)對應(yīng)的UnicodeEncodeError的錯誤的吃谣。

所以乞封,諸如此類的問題,如果搞懂了之前的邏輯岗憋,那么自然很容易理解其錯誤的根源肃晚,并找到解決辦法。

即仔戈,知其所以然关串,之后拧廊,更容易,知其然晋修。

下面就來吧碾,故意的:

  • 再現(xiàn),出各種Python 2.x中所常見的字符的編碼解碼等方面的錯誤飞蚓;
  • 然后幫你找到問題的根本原因滤港;
  • 進(jìn)而找到問題所對應(yīng)的解決辦法;

Python 2.x的字符編碼本身的設(shè)計(jì)的邏輯:str和unicode

想要了解Python 2.x中趴拧,字符串編解碼的問題和原因溅漾,首先搞懂Python 2.x中在字符串的方面是如何設(shè)計(jì)的,其主要分兩大類:str和unicode著榴。

對于str和unicode的確切含義添履,以及如何互相轉(zhuǎn)換,以及Python 2.x和Python 3.x中的bytes和str脑又,有何區(qū)別等內(nèi)容

之前已經(jīng)詳盡的總結(jié)了:

【整理】Python中字符編碼的總結(jié)和對比:Python 2.x的str和unicode vs Python 3.x的bytes和str

不了解的暮胧,也是需要去看懂,然后才能真正明白下面的問題的原因的问麸。

Python中常見字符的編碼和解碼方面的錯誤的現(xiàn)象往衷,原因,及其解決辦法

提醒:

1.下面的代碼严卖,如果想要拷貝粘貼到文件中去測試的話席舍,請注意文本本身所用編碼。

未必一定是聲明的那個編碼哮笆;

詳情請自己看代碼中的中文說明来颤。

不過最簡單的是,直接右鍵另存為對應(yīng)的python文件稠肘,省去你拷貝粘貼轉(zhuǎn)碼等煩心事了福铅。

2.關(guān)于代碼編輯器,推薦用Notepad++:

【crifan推薦】輕量級文本編輯器项阴,Notepad最佳替代品:Notepad++

3.其中對于文件轉(zhuǎn)換編碼等事宜滑黔,不了解的可以參考:

用Notepad++實(shí)現(xiàn)不同字符編碼之間的轉(zhuǎn)換

Python中,想要將某字符串解碼為對應(yīng)的Unicode环揽,但是所使用的編碼類型和字符串本身的編碼不匹配

現(xiàn)象

字符串本身拷沸,是某種編碼類型的字符串,但是結(jié)果將其解碼為對應(yīng)的Unicode時薯演,卻指定了另外一種編碼類型撞芍,導(dǎo)致無法正常的解碼為對應(yīng)的Unicode,而出現(xiàn)UnicodeDecodeError之類的錯誤跨扮。

比如用UTF-8去解碼GBK的字符串:

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【總結(jié)】Python中常見字符編碼和解碼方面的錯誤及其解決辦法
http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution

Author:     Crifan
Verison:    2012-11-29
-------------------------------------------------------------------------------
"""

def python2xDecodeGbkWithUtf8():
    zhcnActualGbk = "此處你所看到的中文字符所處的環(huán)境是:\r\n1.當(dāng)前文件用聲明的編碼是UTF-8序无。但是后來經(jīng)過證明验毡,此處實(shí)際上聲明為GBK還是UTF-8,對于字符串本身的編碼帝嗡,沒影響晶通。字符串本身的編碼,之和當(dāng)前文件的編碼有關(guān)哟玷;\r\n2.此處實(shí)際上文件本身卻是用的GBK編碼狮辽,所以你看到的當(dāng)前的字符串也是GBK的。所以巢寡,后面要演示的:\r\n3.對于GBK的字符喉脖,指定用UTF-8方式去解碼,則會出錯抑月。\r\n4.但是由于當(dāng)前字符是GBK的树叽,而后面要print打印出來到Windows的cmd中,其中cmd編碼(默認(rèn))為GBK谦絮,所以题诵,print函數(shù)是,不會出錯层皱,可以正確顯示此處中文字符的";
    print "zhcnActualGbk=",zhcnActualGbk; #此處是可以正常打印出上述中文字符的
    zhcnUnicode = zhcnActualGbk.decode("UTF-8"); #UnicodeDecodeError: 'utf8' codec can't decode byte 0xb4 in position 0: invalid start byte
    print "zhcnUnicode=",zhcnUnicode; #上述解碼出錯性锭,更不可能執(zhí)行到這里的print了
 
###############################################################################
if __name__=="__main__":
    python2xDecodeGbkWithUtf8();

要說明的是,此處是叫胖,只是為了代碼演示草冈,所以很明顯,就直接看出錯誤了臭家。

但是實(shí)際的編程過程中疲陕,由于很多時候情況很復(fù)雜方淤,未必立刻會意識到或注意到钉赁,編碼類型弄錯了,所以携茂,也還是需要注意這種情況的你踩。

原因

如上所述,想要把某種編碼的字符串解碼為Unicode讳苦;

字符串是A編碼的(GBK)带膜,但是卻用B編碼(UTF-8)去解碼,導(dǎo)致出現(xiàn)UnicodeDecodeError錯誤鸳谜;

解決辦法

使用和字符串本身編碼相同的編碼膝藕,去解碼,就可以正常的解碼為Unicode了咐扭。

修改后的代碼如下:
python_2.x_decode_gbk_use_gbk.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【總結(jié)】Python中常見字符編碼和解碼方面的錯誤及其解決辦法
http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution

Author:     Crifan
Verison:    2012-11-29
-------------------------------------------------------------------------------
"""

def python2xDecodeGbkWithGbk():
    zhcnActualGbk = "此處你所看到的中文字符所處的環(huán)境是:\r\n1.當(dāng)前文件用聲明的編碼是UTF-8芭挽。但是后來經(jīng)過證明滑废,此處實(shí)際上聲明為GBK還是UTF-8,對于字符串本身的編碼袜爪,沒影響蠕趁。字符串本身的編碼,之和當(dāng)前文件的編碼有關(guān)辛馆;\r\n2.此處實(shí)際上文件本身卻是用的GBK編碼俺陋,所以你看到的當(dāng)前的字符串也是GBK的。所以昙篙,后面要演示的:\r\n3.對于GBK的字符腊状,使用同樣的GBK去解碼,則不會出錯了瓢对。\r\n4.而解碼后得到的Unicode字符串寿酌,也可以正常在Windows的默認(rèn)編碼為GBK的cmd中顯示了。其中硕蛹,內(nèi)部會自動將Unicode編碼為GBK然后送到cmd中顯示的醇疼。";
    print "zhcnActualGbk=",zhcnActualGbk; #此處是可以正常打印出上述中文字符的
    zhcnUnicode = zhcnActualGbk.decode("GBK"); #此處使用和字符串本身一致的GBK解碼,就可以正常解碼為Unicode了
    print "zhcnUnicode=",zhcnUnicode; #此處就可以正常輸出Unicode字符串了法焰。內(nèi)部會自動將Unicode編碼為GBK秧荆,然后送到cmd中顯示的
 
###############################################################################
if __name__=="__main__":
    python2xDecodeGbkWithGbk();

舉一反三

如果你以后遇到類似的,UnicodeDecodeError埃仪,那么說明是Unicode在解碼方面的錯誤乙濒,肯定是將某種編碼的字符串,解碼為Unicode的過程中卵蛉,出現(xiàn)的錯誤颁股。

而錯誤原因,也往往都是編碼類型不匹配傻丝,然后就可以去檢查一下甘有,是不是字符串本身的編碼,和你在調(diào)用decode時所設(shè)置的編碼不匹配葡缰。

Python中亏掀,打印字符串時,字符串本身的編碼泛释,與輸出終端中所用編碼不匹配

現(xiàn)象

字符串本身滤愕,是某種編碼的,但是輸出怜校,顯示间影,到終端時,終端所使用編碼茄茁,和你字符串的編碼不一樣魂贬,導(dǎo)致無法正常顯示蔓搞。

比較常見的是,本身是UTF-8類型的字符串随橘,但是卻將其輸出到Windows的cmd中喂分,而cmd中默認(rèn)是GBK編碼的,導(dǎo)致兩者不匹配机蔗,所以打印字符串時蒲祈,出現(xiàn)亂碼:

python_2.x_print_utf8_to_gbk.py
#!/usr/bin/python
# -- coding: utf-8 --
"""
-------------------------------------------------------------------------------
Function:
【總結(jié)】Python中常見字符編碼和解碼方面的錯誤及其解決辦法
http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution

Author: Crifan
Verison:2012-11-29
-------------------------------------------------------------------------------
"""
 
def python2xPrintUtf8ToGbk():
zhcnUtf8 = "此處你所看到的中文字符所處的環(huán)境是:\r\n1.當(dāng)前文件用聲明的編碼是UTF-8。但是后來經(jīng)過證明萝嘁,此處實(shí)際上聲明為GBK還是UTF-8梆掸,對于字符串本身的編碼,沒影響牙言。字符串本身的編碼酸钦,只和當(dāng)前文件的編碼有關(guān);\r\n2.不過呢咱枉,此處文件本身的編碼的確是UTF-8的卑硫,所以你看到的當(dāng)前的字符串也是UTF-8編碼的。所以蚕断,后面要演示的:\r\n3.對于UTF-8的字符欢伏,去打印輸出到Windows的默認(rèn)編碼為GBK的cmd中,就會出現(xiàn)亂碼錯了亿乳。";
print "zhcnUtf8=",zhcnUtf8; #把UTF-8的字符串硝拧,輸出到GBK的cmd中,結(jié)果顯示的都是亂碼:
 
# zhcnUtf8= 姝ゅ浣犳墍鐪嬪埌鐨勪腑鏂囧瓧絎︽墍澶勭殑鐜鏄細(xì)
# 1.褰撳墠鏂囦歡鐢ㄥ0鏄庣殑緙栫爜鏄疷TF-8銆備絾鏄悗鏉ョ粡榪囪瘉鏄庯紝姝ゅ瀹為檯涓婂0鏄庝負(fù)GBK榪樻槸UTF-8錛屽浜庡瓧絎︿覆鏈韓鐨勭紪鐮侊紝娌″獎鍝嶃€傚瓧絎︿覆鏈韓鐨勭紪鐮侊紝鍙拰褰撳墠鏂囦
# 歡鐨勭紪鐮佹湁鍏籌紱
# 2.涓嶈繃鍛紝姝ゅ鏂囦歡鏈韓鐨勭紪鐮佺殑紜槸UTF-8鐨勶紝鎵€浠ヤ綘鐪嬪埌鐨勫綋鍓嶇殑瀛楃涓蹭篃鏄疷TF-8緙栫爜鐨勩€傛墍浠ワ紝鍚庨潰瑕佹紨紺虹殑錛?
# 3.瀵逛簬UTF-8鐨勫瓧絎︼紝鍘繪墦鍗拌緭鍑哄埌Windows鐨勯粯璁ょ紪鐮佷負(fù)GBK鐨刢md涓紝灝變細(xì)鍑洪敊浜嗐€
 
###############################################################################
if __name__=="__main__":
python2xPrintUtf8ToGbk();

原因

把Python文件中的字符串葛假,該P(yáng)ython文件是UTF-8的障陶,所以該字符串也是UTF-8編碼的,輸出到Windows的cmd中聊训,而cmd中默認(rèn)編碼為GBK抱究,即

把UTF-8的字符串,在GBK的cmd上顯示魔眨,則出現(xiàn)了亂碼媳维。

解決辦法

目的是為了是要輸出的字符串的編碼酿雪,是Unicode遏暴,或者和目標(biāo)輸出終端的編碼一致,就可以正常輸出了指黎。

所以可以把UTF-8的字符朋凉,解碼為對應(yīng)的Unicode,醋安。

(也可以進(jìn)一步的杂彭,把Unicode字符串墓毒,編碼為GBK)

然后再輸出到GBK的cmd中,就可以正常顯示亲怠,不是亂碼了:

python_2.x_dec_utf8_then_to_gbk.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【總結(jié)】Python中常見字符編碼和解碼方面的錯誤及其解決辦法
http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution
 
Author: Crifan
Verison:2012-11-29
-------------------------------------------------------------------------------
"""
 
def python2xDecodeUtf8ThenOutputToGbk():
zhcnUtf8 = "此處你所看到的中文字符所處的環(huán)境是:\r\n1.當(dāng)前文件用聲明的編碼是UTF-8所计。但是后來經(jīng)過證明,此處實(shí)際上聲明為GBK還是UTF-8团秽,對于字符串本身的編碼主胧,沒影響。字符串本身的編碼习勤,只和當(dāng)前文件的編碼有關(guān)踪栋;\r\n2.不過呢,此處文件本身的編碼的確是UTF-8的图毕,所以你看到的當(dāng)前的字符串也是UTF-8編碼的夷都。所以,后面要演示的:\r\n3.對于UTF-8的字符予颤,先去指定用UTF-8去解碼為Unicode囤官,然后再去輸出到Windows的默認(rèn)編碼為GBK的cmd中,就不會出現(xiàn)亂碼錯了蛤虐≈文茫或者是將得到的Unicode字符串,再編碼為GBK笆焰,然后再輸出到GBK的cmd劫谅,也是同樣的效果。";
print "zhcnUtf8=",zhcnUtf8; #把UTF-8的字符串嚷掠,輸出到GBK的cmd中捏检,結(jié)果顯示的都是亂碼:
# zhcnUtf8= 姝ゅ浣犳墍鐪嬪埌鐨勪腑鏂囧瓧絎︽墍澶勭殑鐜鏄細(xì) ......紝灝變細(xì)鍑洪敊浜嗐€
 
decodedUnicode = zhcnUtf8.decode("UTF-8"); #用UTF-8解碼UTF-8的字符串位Unicode
print "decodedUnicode=",decodedUnicode; #此處就可以正常輸出了,不會顯示亂碼了
decodedUnicodeThenEncodedToGbk = decodedUnicode.encode("GBK"); #將Unicode的字符串不皆,編碼為GBK
print "decodedUnicodeThenEncodedToGbk=",decodedUnicodeThenEncodedToGbk; #然后再輸出到GBK編碼的cmd贯城,也是同樣可以正確顯示的
 
###############################################################################
if __name__=="__main__":
python2xDecodeUtf8ThenOutputToGbk();

舉一反三

以后如果再遇到類似的亂碼,先去確定你的字符串本身是什么編碼的霹娄。

再去確定能犯,你所要輸出的終端目標(biāo)中,所用的編碼是什么樣的犬耻。

其中踩晶,輸出的終端,此處舉例所用的是枕磁,windows的cmd渡蜻,其他還有可能是輸出內(nèi)容到文件中,其中還涉及文件所用的編碼是什么,這些都要自己搞清楚的茸苇。

總之排苍,確保字符串編碼類型,和輸出所用的編碼類型学密,兩者是一致的淘衙,就不會出現(xiàn)亂碼了。

Python中腻暮,打印含某些特殊字符的Unicode類型字符串幔翰,但是輸出終端中字符編碼集中不包含這些特殊字符

現(xiàn)象

雖然已經(jīng)獲得了Unicode的字符串了,但是當(dāng)打印Unicode類型的字符串西壮,到某些終端中時遗增,結(jié)果卻還是出錯了。

比如款青,下面的例子中做修,就是把Unicode字符串,打印到Windows的cmd中抡草,結(jié)果出錯:

python_2.x_print_unicode_still_error.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【總結(jié)】Python中常見字符編碼和解碼方面的錯誤及其解決辦法
http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution
 
Author: Crifan
Verison:2012-11-29
-------------------------------------------------------------------------------
"""
  
#任何字符饰及,都可以在:
#http://unicodelookup.com/
#中,查找到對應(yīng)的unicode的值
 
def python2xPrintUnicodeStillError():
#http://zhidao.baidu.com/question/500133781.html
slashUStr = "\\u3232\\u6674"; #(有) 晴
decodedUniChars = slashUStr.decode("unicode-escape"); #此處已經(jīng)可以正常獲得對應(yīng)的兩個Unicode字符了
unicodeButContainSpecialChar = decodedUniChars;
print "unicodeButContainSpecialChar=",unicodeButContainSpecialChar;
 
#此處在GBK編碼的cmd中輸出的話康震,會出現(xiàn)錯誤的:
#UnicodeEncodeError: 'gbk' codec can't encode character u'\u3232' in position 0: illegal multibyte sequence
#那是因?yàn)榱呛琔nicode字符:0x3232,是個特殊字符腿短,而此字符屏箍,在GBK編碼字符集中,本身就不包含此特殊字符橘忱,所以當(dāng)然沒法把這個特殊字符編碼為對應(yīng)的GBK字符赴魁,所以出錯,更無法顯示
 
###############################################################################
if __name__=="__main__":
python2xPrintUnicodeStillError();

原因

上述過程中钝诚,雖然已經(jīng)獲得了正確的unicode字符串了颖御,但是由于此unicode字符串中包含了一個特殊字符,即那個\u3232凝颇,對應(yīng)的字符潘拱,顯示出來,像是左右括號中間一個"有"字拧略,即類似于這樣的:

(有)

而此特殊字符芦岂,GBK字符集中沒有,不存在辑鲤,所以無法將對應(yīng)的Unicode字符盔腔,編碼為對應(yīng)的GBK字符杠茬,所以出現(xiàn)UnicodeEncodeError月褥,更無法打印出來

注:

對于任何字符弛随,都可以去這里:

http://unicodelookup.com/

而查到,對應(yīng)的unicode的值宁赤,html中的寫法舀透。

提醒:

可以通過輸入:

0x3232

而查到該特殊字符。

解決辦法

解決辦法决左,則是不同情況愕够,不同處理:

(1)如果對于這些特殊字符,你不是很關(guān)心佛猛,即使不顯示也無所謂惑芭,但是希望剩下的,其他大多數(shù)的正常的字符都能顯示继找。

即遂跟,忽略掉特殊字符,顯示哪些能顯示的字符婴渡, 那么可以改為如下代碼:

python_2.x_print_unicode_omit_special.py

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【總結(jié)】Python中常見字符編碼和解碼方面的錯誤及其解決辦法
http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution
 
Author: Crifan
Verison:2012-11-29
-------------------------------------------------------------------------------
"""
  
#任何字符幻锁,都可以在:
#http://unicodelookup.com/
#中,查找到對應(yīng)的unicode的值
 
def python2xPrintUnicodeOmitSpecial():
#http://zhidao.baidu.com/question/500133781.html
slashUStr = "\\u3232\\u6674"; #(有) 晴
decodedUniChars = slashUStr.decode("unicode-escape"); #此處已經(jīng)可以正常獲得對應(yīng)的兩個Unicode字符了
unicodeButContainSpecialChar = decodedUniChars;
#print "unicodeButContainSpecialChar=",unicodeButContainSpecialChar;
 
#此處在GBK編碼的cmd中輸出的話边臼,會出現(xiàn)錯誤的:
#UnicodeEncodeError: 'gbk' codec can't encode character u'\u3232' in position 0: illegal multibyte sequence
#那是因?yàn)楹宥琔nicode字符:0x3232,是個特殊字符柠并,而此字符岭接,在GBK編碼字符集中,本身就不包含此特殊字符臼予,所以當(dāng)然沒法把這個特殊字符編碼為對應(yīng)的GBK字符亿傅,所以出錯,更無法顯示
 
#如果只是想要:
#顯示那些正澄疗埽可以顯示的字符葵擎,忽略個別特殊不能顯示的字符
#那么可以改為如下代碼:
encodedShowableGbk = unicodeButContainSpecialChar.encode("GBK", "ignore");
print "encodedShowableGbk=",encodedShowableGbk; #encodedShowableGbk= 晴
 
###############################################################################
if __name__=="__main__":
python2xPrintUnicodeOmitSpecial();

注:我之前遇到的一個情況,就是通過添加ignore去處理的:

【已解決】UnicodeEncodeError: ‘gbk’ codec can’t encode character u’\u200e’ in position 43: illegal multibyte sequence

(2)如果必須要顯示這些字符半哟,或者說必須要保留這些字符酬滤。那么本身對于打印這個需求來說,是可以不打印的寓涨,因?yàn)楸旧硪勋@得了正常的Unicode字符了盯串。

然后剩下的,只是盡量你自己所需要的后續(xù)的處理即可戒良。

即体捏, 已經(jīng)得到了正確的unicode字符了,后續(xù)該咋辦咋辦,可以不打印的時候几缭,就不打印河泳,也就不會出錯了。

舉一反三

如果以后遇到這種年栓,雖然已獲得了Unicode字符串拆挥,但是還是無法打印等情況,則就要注意去調(diào)查一下某抓,是否是由于此處有特殊字符纸兔,不存在于輸出目標(biāo)所用字符集中,才導(dǎo)致此問題的否副。

進(jìn)一步的舉一反三

如果你對于上述代碼中的encode中的ignore不熟悉汉矿,那么你自然應(yīng)該想到,去了解备禀,去學(xué)習(xí)這方面的內(nèi)容负甸。

然后通過google搜:

unicode encode ignore

就可以找到Python官網(wǎng)的解釋了:
Unicode HOWTO — Python v2.7.3 documentation

而如果你再稍微積極思考的話,就會想到:

既然encode有個ignore參數(shù)痹届,那是不是還有其他參數(shù)呻待?

對應(yīng)的函數(shù)原型是啥?

由此队腐,去通過Python的自帶手冊蚕捉,就找到對應(yīng)你所要的內(nèi)容了:

str.encode([encoding[, errors]])

Return an encoded version of the string. Default encoding is the current default string encoding. errors may be given to set a different error handling scheme. The default for errors is 'strict', meaning that encoding errors raise a UnicodeError. Other possible values are 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' and any other name registered via codecs.register_error(), see section Codec Base Classes. For a list of possible encodings, see section Standard Encodings.

New in version 2.0.

Changed in version 2.3: Support for 'xmlcharrefreplace' and 'backslashreplace' and other error handling schemes added.

Changed in version 2.7: Support for keyword arguments added.

然后再細(xì)心些的話,還會發(fā)現(xiàn)手冊中柴淘,str.encode上面迫淹,還有個對應(yīng)的decode函數(shù),也是有一些相關(guān)的參數(shù)为严,比如’ignore’, ‘replace’的:

str.decode([encoding[, errors]])

Decodes the string using the codec registered for encoding. encoding defaults to the default string encoding. errors may be given to set a different error handling scheme. The default is 'strict', meaning that encoding errors raise UnicodeError. Other possible values are 'ignore', 'replace' and any other name registered via codecs.register_error(), see section Codec Base Classes.

New in version 2.2.

Changed in version 2.3: Support for other error handling schemes added.

Changed in version 2.7: Support for keyword arguments added.

由此敛熬,多去學(xué)習(xí)官網(wǎng)的手冊,自然會了解到第股,函數(shù)的最權(quán)威的解釋和用法应民。

總結(jié)

凡是都是,要積極思考夕吻,通過有限的經(jīng)驗(yàn)诲锹,去努力獲得更多的,相關(guān)知識的總結(jié)涉馅。

而此處上面的這些總結(jié)归园,相應(yīng)地,也的確是必須經(jīng)過一堆的錯誤稚矿,從開始的一頭霧水庸诱,到最后的漸漸清晰捻浦,以及最終的,搞懂邏輯和背后的原因桥爽。

總之朱灿,想要學(xué)好Python或其他語言,都還是要足夠的積累聚谁,足夠的練習(xí)母剥,以及及時的總結(jié)滞诺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末形导,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子习霹,更是在濱河造成了極大的恐慌朵耕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淋叶,死亡現(xiàn)場離奇詭異阎曹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)煞檩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門处嫌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斟湃,你說我怎么就攤上這事熏迹。” “怎么了凝赛?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵注暗,是天一觀的道長。 經(jīng)常有香客問我墓猎,道長捆昏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任毙沾,我火速辦了婚禮骗卜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘左胞。我一直安慰自己膨俐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布罩句。 她就那樣靜靜地躺著焚刺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪门烂。 梳的紋絲不亂的頭發(fā)上乳愉,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天兄淫,我揣著相機(jī)與錄音,去河邊找鬼蔓姚。 笑死捕虽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坡脐。 我是一名探鬼主播泄私,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼备闲!你這毒婦竟也來了晌端?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤恬砂,失蹤者是張志新(化名)和其女友劉穎咧纠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泻骤,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漆羔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狱掂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片演痒。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖趋惨,靈堂內(nèi)的尸體忽然破棺而出鸟顺,到底是詐尸還是另有隱情,我是刑警寧澤希柿,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布诊沪,位于F島的核電站,受9級特大地震影響曾撤,放射性物質(zhì)發(fā)生泄漏端姚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一挤悉、第九天 我趴在偏房一處隱蔽的房頂上張望渐裸。 院中可真熱鬧,春花似錦装悲、人聲如沸昏鹃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洞渤。三九已至,卻和暖如春属瓣,著一層夾襖步出監(jiān)牢的瞬間载迄,已是汗流浹背讯柔。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留护昧,地道東北人魂迄。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像惋耙,于是被迫代替她去往敵國和親捣炬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容