最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中字符編碼簡(jiǎn)介、方法及使用建議

 更新時(shí)間:2015年01月08日 09:02:22   投稿:hebedich  
這篇文章主要介紹了Python中字符編碼簡(jiǎn)介、方法及使用建議,需要的朋友可以參考下

1. 字符編碼簡(jiǎn)介

1.1. ASCII

ASCII(American Standard Code for Information Interchange),是一種單字節(jié)的編碼。計(jì)算機(jī)世界里一開(kāi)始只有英文,而單字節(jié)可以表示256個(gè)不同的字符,可以表示所有的英文字符和許多的控制符號(hào)。不過(guò)ASCII只用到了其中的一半(\x80以下),這也是MBCS得以實(shí)現(xiàn)的基礎(chǔ)。

1.2. MBCS

然而計(jì)算機(jī)世界里很快就有了其他語(yǔ)言,單字節(jié)的ASCII已無(wú)法滿(mǎn)足需求。后來(lái)每個(gè)語(yǔ)言就制定了一套自己的編碼,由于單字節(jié)能表示的字符太少,而且同時(shí)也需要與ASCII編碼保持兼容,所以這些編碼紛紛使用了多字節(jié)來(lái)表示字符,如GBxxx、BIGxxx等等,他們的規(guī)則是,如果第一個(gè)字節(jié)是\x80以下,則仍然表示ASCII字符;而如果是\x80以上,則跟下一個(gè)字節(jié)一起(共兩個(gè)字節(jié))表示一個(gè)字符,然后跳過(guò)下一個(gè)字節(jié),繼續(xù)往下判斷。

這里,IBM發(fā)明了一個(gè)叫Code Page的概念,將這些編碼都收入囊中并分配頁(yè)碼,GBK是第936頁(yè),也就是CP936。所以,也可以使用CP936表示GBK。

MBCS(Multi-Byte Character Set)是這些編碼的統(tǒng)稱(chēng)。目前為止大家都是用了雙字節(jié),所以有時(shí)候也叫做DBCS(Double-Byte Character Set)。必須明確的是,MBCS并不是某一種特定的編碼,Windows里根據(jù)你設(shè)定的區(qū)域不同,MBCS指代不同的編碼,而Linux里無(wú)法使用MBCS作為編碼。在Windows中你看不到MBCS這幾個(gè)字符,因?yàn)槲④洖榱烁友髿?,使用了ANSI來(lái)嚇唬人,記事本的另存為對(duì)話(huà)框里編碼ANSI就是MBCS。同時(shí),在簡(jiǎn)體中文Windows默認(rèn)的區(qū)域設(shè)定里,指代GBK。

1.3. Unicode

后來(lái),有人開(kāi)始覺(jué)得太多編碼導(dǎo)致世界變得過(guò)于復(fù)雜了,讓人腦袋疼,于是大家坐在一起拍腦袋想出來(lái)一個(gè)方法:所有語(yǔ)言的字符都用同一種字符集來(lái)表示,這就是Unicode。

最初的Unicode標(biāo)準(zhǔn)UCS-2使用兩個(gè)字節(jié)表示一個(gè)字符,所以你常??梢月?tīng)到Unicode使用兩個(gè)字節(jié)表示一個(gè)字符的說(shuō)法。但過(guò)了不久有人覺(jué)得256*256太少了,還是不夠用,于是出現(xiàn)了UCS-4標(biāo)準(zhǔn),它使用4個(gè)字節(jié)表示一個(gè)字符,不過(guò)我們用的最多的仍然是UCS-2。

UCS(Unicode Character Set)還僅僅是字符對(duì)應(yīng)碼位的一張表而已,比如"漢"這個(gè)字的碼位是6C49。字符具體如何傳輸和儲(chǔ)存則是由UTF(UCS Transformation Format)來(lái)負(fù)責(zé)。

一開(kāi)始這事很簡(jiǎn)單,直接使用UCS的碼位來(lái)保存,這就是UTF-16,比如,"漢"直接使用\x6C\x49保存(UTF-16-BE),或是倒過(guò)來(lái)使用\x49\x6C保存(UTF-16-LE)。但用著用著美國(guó)人覺(jué)得自己吃了大虧,以前英文字母只需要一個(gè)字節(jié)就能保存了,現(xiàn)在大鍋飯一吃變成了兩個(gè)字節(jié),空間消耗大了一倍……于是UTF-8橫空出世。

UTF-8是一種很別扭的編碼,具體表現(xiàn)在他是變長(zhǎng)的,并且兼容ASCII,ASCII字符使用1字節(jié)表示。然而這里省了的必定是從別的地方摳出來(lái)的,你肯定也聽(tīng)說(shuō)過(guò)UTF-8里中文字符使用3個(gè)字節(jié)來(lái)保存吧?4個(gè)字節(jié)保存的字符更是在淚奔……(具體UCS-2是怎么變成UTF-8的請(qǐng)自行搜索)

另外值得一提的是BOM(Byte Order Mark)。我們?cè)趦?chǔ)存文件時(shí),文件使用的編碼并沒(méi)有保存,打開(kāi)時(shí)則需要我們記住原先保存時(shí)使用的編碼并使用這個(gè)編碼打開(kāi),這樣一來(lái)就產(chǎn)生了許多麻煩。(你可能想說(shuō)記事本打開(kāi)文件時(shí)并沒(méi)有讓選編碼?不妨先打開(kāi)記事本再使用文件 -> 打開(kāi)看看)而UTF則引入了BOM來(lái)表示自身編碼,如果一開(kāi)始讀入的幾個(gè)字節(jié)是其中之一,則代表接下來(lái)要讀取的文字使用的編碼是相應(yīng)的編碼:

BOM_UTF8 '\xef\xbb\xbf'
BOM_UTF16_LE '\xff\xfe'
BOM_UTF16_BE '\xfe\xff'

并不是所有的編輯器都會(huì)寫(xiě)入BOM,但即使沒(méi)有BOM,Unicode還是可以讀取的,只是像MBCS的編碼一樣,需要另行指定具體的編碼,否則解碼將會(huì)失敗。

你可能聽(tīng)說(shuō)過(guò)UTF-8不需要BOM,這種說(shuō)法是不對(duì)的,只是絕大多數(shù)編輯器在沒(méi)有BOM時(shí)都是以UTF-8作為默認(rèn)編碼讀取。即使是保存時(shí)默認(rèn)使用ANSI(MBCS)的記事本,在讀取文件時(shí)也是先使用UTF-8測(cè)試編碼,如果可以成功解碼,則使用UTF-8解碼。記事本這個(gè)別扭的做法造成了一個(gè)BUG:如果你新建文本文件并輸入"姹塧"然后使用ANSI(MBCS)保存,再打開(kāi)就會(huì)變成"漢a",你不妨試試 :)

2. Python2.x中的編碼問(wèn)題

2.1. str和unicode
str和unicode都是basestring的子類(lèi)。嚴(yán)格意義上說(shuō),str其實(shí)是字節(jié)串,它是unicode經(jīng)過(guò)編碼后的字節(jié)組成的序列。對(duì)UTF-8編碼的str'漢'使用len()函數(shù)時(shí),結(jié)果是3,因?yàn)閷?shí)際上,UTF-8編碼的'漢' == '\xE6\xB1\x89'。

unicode才是真正意義上的字符串,對(duì)字節(jié)串str使用正確的字符編碼進(jìn)行解碼后獲得,并且len(u'漢') == 1。

再來(lái)看看encode()和decode()兩個(gè)basestring的實(shí)例方法,理解了str和unicode的區(qū)別后,這兩個(gè)方法就不會(huì)再混淆了:

復(fù)制代碼 代碼如下:

# coding: UTF-8
u = u'漢'
print repr(u) # u'\u6c49'
s = u.encode('UTF-8')
print repr(s) # '\xe6\xb1\x89'
u2 = s.decode('UTF-8')
print repr(u2) # u'\u6c49'
# 對(duì)unicode進(jìn)行解碼是錯(cuò)誤的
# s2 = u.decode('UTF-8')
# 同樣,對(duì)str進(jìn)行編碼也是錯(cuò)誤的
# u2 = s.encode('UTF-8')

需要注意的是,雖然對(duì)str調(diào)用encode()方法是錯(cuò)誤的,但實(shí)際上Python不會(huì)拋出異常,而是返回另外一個(gè)相同內(nèi)容但不同id的str;對(duì)unicode調(diào)用decode()方法也是這樣。很不理解為什么不把encode()和decode()分別放在unicode和str中而是都放在basestring中,但既然已經(jīng)這樣了,我們就小心避免犯錯(cuò)吧。

2.2. 字符編碼聲明

源代碼文件中,如果有用到非ASCII字符,則需要在文件頭部進(jìn)行字符編碼的聲明,如下:

復(fù)制代碼 代碼如下:

#-*- coding: UTF-8 -*-

實(shí)際上Python只檢查#、coding和編碼字符串,其他的字符都是為了美觀加上的。另外,Python中可用的字符編碼有很多,并且還有許多別名,還不區(qū)分大小寫(xiě),比如UTF-8可以寫(xiě)成u8。參見(jiàn)http://docs.python.org/library/codecs.html#standard-encodings。

另外需要注意的是聲明的編碼必須與文件實(shí)際保存時(shí)用的編碼一致,否則很大幾率會(huì)出現(xiàn)代碼解析異常?,F(xiàn)在的IDE一般會(huì)自動(dòng)處理這種情況,改變聲明后同時(shí)換成聲明的編碼保存,但文本編輯器控們需要小心 :)

2.3. 讀寫(xiě)文件

內(nèi)置的open()方法打開(kāi)文件時(shí),read()讀取的是str,讀取后需要使用正確的編碼格式進(jìn)行decode()。write()寫(xiě)入時(shí),如果參數(shù)是unicode,則需要使用你希望寫(xiě)入的編碼進(jìn)行encode(),如果是其他編碼格式的str,則需要先用該str的編碼進(jìn)行decode(),轉(zhuǎn)成unicode后再使用寫(xiě)入的編碼進(jìn)行encode()。如果直接將unicode作為參數(shù)傳入write()方法,Python將先使用源代碼文件聲明的字符編碼進(jìn)行編碼然后寫(xiě)入。

復(fù)制代碼 代碼如下:

# coding: UTF-8
f = open('test.txt')
s = f.read()
f.close()
print type(s) # <type 'str'>
# 已知是GBK編碼,解碼成unicode
u = s.decode('GBK')
f = open('test.txt', 'w')
# 編碼成UTF-8編碼的str
s = u.encode('UTF-8')
f.write(s)
f.close()

另外,模塊codecs提供了一個(gè)open()方法,可以指定一個(gè)編碼打開(kāi)文件,使用這個(gè)方法打開(kāi)的文件讀取返回的將是unicode。寫(xiě)入時(shí),如果參數(shù)是unicode,則使用open()時(shí)指定的編碼進(jìn)行編碼后寫(xiě)入;如果是str,則先根據(jù)源代碼文件聲明的字符編碼,解碼成unicode后再進(jìn)行前述操作。相對(duì)內(nèi)置的open()來(lái)說(shuō),這個(gè)方法比較不容易在編碼上出現(xiàn)問(wèn)題。

復(fù)制代碼 代碼如下:

# coding: GBK
import codecs
f = codecs.open('test.txt', encoding='UTF-8')
u = f.read()
f.close()
print type(u) # <type 'unicode'>
f = codecs.open('test.txt', 'a', encoding='UTF-8')
# 寫(xiě)入unicode
f.write(u)
# 寫(xiě)入str,自動(dòng)進(jìn)行解碼編碼操作
# GBK編碼的str
s = '漢'
print repr(s) # '\xba\xba'
# 這里會(huì)先將GBK編碼的str解碼為unicode再編碼為UTF-8寫(xiě)入
f.write(s)
f.close()

2.4. 與編碼相關(guān)的方法
sys/locale模塊中提供了一些獲取當(dāng)前環(huán)境下的默認(rèn)編碼的方法。

復(fù)制代碼 代碼如下:

# coding:gbk
import sys
import locale
def p(f):
    print '%s.%s(): %s' % (f.__module__, f.__name__, f())
# 返回當(dāng)前系統(tǒng)所使用的默認(rèn)字符編碼
p(sys.getdefaultencoding)
# 返回用于轉(zhuǎn)換Unicode文件名至系統(tǒng)文件名所使用的編碼
p(sys.getfilesystemencoding)
# 獲取默認(rèn)的區(qū)域設(shè)置并返回元祖(語(yǔ)言, 編碼)
p(locale.getdefaultlocale)
# 返回用戶(hù)設(shè)定的文本數(shù)據(jù)編碼
# 文檔提到this function only returns a guess
p(locale.getpreferredencoding)
# \xba\xba是'漢'的GBK編碼
# mbcs是不推薦使用的編碼,這里僅作測(cè)試表明為什么不應(yīng)該用
print r"'\xba\xba'.decode('mbcs'):", repr('\xba\xba'.decode('mbcs'))
#在筆者的Windows上的結(jié)果(區(qū)域設(shè)置為中文(簡(jiǎn)體, 中國(guó)))
#sys.getdefaultencoding(): gbk
#sys.getfilesystemencoding(): mbcs
#locale.getdefaultlocale(): ('zh_CN', 'cp936')
#locale.getpreferredencoding(): cp936
#'\xba\xba'.decode('mbcs'): u'\u6c49'

3.一些建議

3.1. 使用字符編碼聲明,并且同一工程中的所有源代碼文件使用相同的字符編碼聲明。
這點(diǎn)是一定要做到的。

3.2. 拋棄str,全部使用unicode。
按引號(hào)前先按一下u最初做起來(lái)確實(shí)很不習(xí)慣而且經(jīng)常會(huì)忘記再跑回去補(bǔ),但如果這么做可以減少90%的編碼問(wèn)題。如果編碼困擾不嚴(yán)重,可以不參考此條。

3.3. 使用codecs.open()替代內(nèi)置的open()。
如果編碼困擾不嚴(yán)重,可以不參考此條。

3.4. 絕對(duì)需要避免使用的字符編碼:MBCS/DBCS和UTF-16。
這里說(shuō)的MBCS不是指GBK什么的都不能用,而是不要使用Python里名為'MBCS'的編碼,除非程序完全不移植。

Python中編碼'MBCS'與'DBCS'是同義詞,指當(dāng)前Windows環(huán)境中MBCS指代的編碼。Linux的Python實(shí)現(xiàn)中沒(méi)有這種編碼,所以一旦移植到Linux一定會(huì)出現(xiàn)異常!另外,只要設(shè)定的Windows系統(tǒng)區(qū)域不同,MBCS指代的編碼也是不一樣的。分別設(shè)定不同的區(qū)域運(yùn)行2.4小節(jié)中的代碼的結(jié)果:

復(fù)制代碼 代碼如下:

#中文(簡(jiǎn)體, 中國(guó))
#sys.getdefaultencoding(): gbk
#sys.getfilesystemencoding(): mbcs
#locale.getdefaultlocale(): ('zh_CN', 'cp936')
#locale.getpreferredencoding(): cp936
#'\xba\xba'.decode('mbcs'): u'\u6c49'
#英語(yǔ)(美國(guó))
#sys.getdefaultencoding(): UTF-8
#sys.getfilesystemencoding(): mbcs
#locale.getdefaultlocale(): ('zh_CN', 'cp1252')
#locale.getpreferredencoding(): cp1252
#'\xba\xba'.decode('mbcs'): u'\xba\xba'
#德語(yǔ)(德國(guó))
#sys.getdefaultencoding(): gbk
#sys.getfilesystemencoding(): mbcs
#locale.getdefaultlocale(): ('zh_CN', 'cp1252')
#locale.getpreferredencoding(): cp1252
#'\xba\xba'.decode('mbcs'): u'\xba\xba'
#日語(yǔ)(日本)
#sys.getdefaultencoding(): gbk
#sys.getfilesystemencoding(): mbcs
#locale.getdefaultlocale(): ('zh_CN', 'cp932')
#locale.getpreferredencoding(): cp932
#'\xba\xba'.decode('mbcs'): u'\uff7a\uff7a'

可見(jiàn),更改區(qū)域后,使用mbcs解碼得到了不正確的結(jié)果,所以,當(dāng)我們需要使用'GBK'時(shí),應(yīng)該直接寫(xiě)'GBK',不要寫(xiě)成'MBCS'。

UTF-16同理,雖然絕大多數(shù)操作系統(tǒng)中'UTF-16'是'UTF-16-LE'的同義詞,但直接寫(xiě)'UTF-16-LE'只是多寫(xiě)3個(gè)字符而已,而萬(wàn)一某個(gè)操作系統(tǒng)中'UTF-16'變成了'UTF-16-BE'的同義詞,就會(huì)有錯(cuò)誤的結(jié)果。實(shí)際上,UTF-16用的相當(dāng)少,但用到的時(shí)候還是需要注意。

相關(guān)文章

  • Python批量修改文件名案例匯總

    Python批量修改文件名案例匯總

    在文件管理和數(shù)據(jù)處理中,批量修改文件名是一項(xiàng)常見(jiàn)且重要的任務(wù),Python作為一種功能強(qiáng)大的編程語(yǔ)言,提供了豐富的庫(kù)和工具來(lái)簡(jiǎn)化這一過(guò)程,本文將結(jié)合實(shí)際案例,詳細(xì)介紹如何通過(guò)Python批量修改文件名,需要的朋友可以參考下
    2024-08-08
  • 使用pytorch完成kaggle貓狗圖像識(shí)別方式

    使用pytorch完成kaggle貓狗圖像識(shí)別方式

    今天小編就為大家分享一篇使用pytorch完成kaggle貓狗圖像識(shí)別方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-01-01
  • 用Python制作簡(jiǎn)單的鋼琴程序的教程

    用Python制作簡(jiǎn)單的鋼琴程序的教程

    這篇文章主要介紹了用Python制作簡(jiǎn)單的鋼琴程序的教程,用鍵盤(pán)演奏、包括變速和變調(diào)等功能的實(shí)現(xiàn),需要的朋友可以參考下
    2015-04-04
  • Python編解碼問(wèn)題及文本文件處理方法詳解

    Python編解碼問(wèn)題及文本文件處理方法詳解

    最近在做一個(gè)項(xiàng)目,因?yàn)槲谋咎幚淼膬?nèi)容是中文,所以不得不面對(duì)python中文處理所帶來(lái)的種種困惑,這篇文章主要給大家介紹了關(guān)于Python編解碼問(wèn)題及文本文件處理方法的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • 用python自動(dòng)生成日歷

    用python自動(dòng)生成日歷

    這篇文章主要介紹了如何用python自動(dòng)生成日歷,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-04-04
  • 關(guān)于Python?中IndexError:list?assignment?index?out?of?range?錯(cuò)誤解決

    關(guān)于Python?中IndexError:list?assignment?index?out?of?rang

    這篇文章主要介紹了Python?中IndexError:list?assignment?index?out?of?range?錯(cuò)誤解決,概述了兩個(gè)常見(jiàn)的列表函數(shù),它們可以幫助我們?cè)谔鎿Q兩個(gè)列表時(shí)幫助我們處理?Python?中的索引錯(cuò)誤,需要的朋友可以參考下
    2023-05-05
  • Python Selenium中等待設(shè)置的實(shí)現(xiàn)

    Python Selenium中等待設(shè)置的實(shí)現(xiàn)

    本文主要介紹了Python Selenium中等待設(shè)置的實(shí)現(xiàn),過(guò)詳實(shí)的示例代碼,深入介紹了顯式等待、隱式等待、自定義等待條件、多重等待條件、頁(yè)面加載狀態(tài)的等待、元素存在與可見(jiàn)性等待、Fluent等待以及異步JavaScript加載的等待,感興趣的可以了解一下
    2023-12-12
  • Python 分享10個(gè)PyCharm技巧

    Python 分享10個(gè)PyCharm技巧

    這篇文章主要介紹了Python 分享10個(gè)PyCharm技巧,今天要跟大家分享幾個(gè)PyCharm小技巧,幫助大家提升工作效率!,需要的朋友可以參考下
    2019-07-07
  • 趣味Python實(shí)戰(zhàn)練習(xí)之自動(dòng)更換桌面壁紙腳本附源碼

    趣味Python實(shí)戰(zhàn)練習(xí)之自動(dòng)更換桌面壁紙腳本附源碼

    讀萬(wàn)卷書(shū)不如行萬(wàn)里路,學(xué)的扎不扎實(shí)要通過(guò)實(shí)戰(zhàn)才能看出來(lái),本篇文章手把手帶你編寫(xiě)一個(gè)自動(dòng)更換桌面壁紙的腳本,代碼簡(jiǎn)潔而且短,相信你一定看得懂,大家可以在過(guò)程中查缺補(bǔ)漏,看看自己掌握程度怎么樣
    2021-10-10
  • 初步解析Python中的yield函數(shù)的用法

    初步解析Python中的yield函數(shù)的用法

    這篇文章主要介紹了Python中的yield函數(shù),yield函數(shù)是生成器中的一個(gè)常用函數(shù),本文來(lái)自于IBM官方網(wǎng)站的開(kāi)發(fā)者文檔的翻譯,需要的朋友可以參考下
    2015-04-04

最新評(píng)論

潢川县| 千阳县| 方山县| 汕尾市| 绵阳市| 仁寿县| 大方县| 揭西县| 南澳县| 上饶市| 栾川县| 临泉县| 虹口区| 辛集市| 社会| 正定县| 麻江县| 新蔡县| 朝阳市| 民和| 南木林县| 新平| 高陵县| 松滋市| 通城县| 蛟河市| 长寿区| 宁安市| 江安县| 永和县| 那曲县| 漳平市| 布尔津县| 汤阴县| 朝阳区| 林州市| 五峰| 平利县| 金寨县| 彭州市| 乃东县|