python2编码问题解决了吗_Python2编码问题
以下內(nèi)容說的都是 python 2.x 版本
簡介
基本概念
Python “幫”你做的事情
推薦姿勢
1、基本概念
我們看到的輸入輸出都是‘字符’(characters),計(jì)算機(jī)(程序)并不能直接處理,需要轉(zhuǎn)化成字節(jié)數(shù)據(jù)(bytes),因?yàn)槌绦蛑荒芴幚?bytes 數(shù)據(jù)。
例如:文件、網(wǎng)絡(luò)傳輸?shù)?#xff0c;處理的都是 bytes 數(shù)據(jù)——二進(jìn)制數(shù)字。
1.1 ASCII / Unicode
孤立的 byte 是毫無意義的,所以我們來賦予他們含義。就引入‘字符集’的概念,‘字符集’就是一個(gè)碼位(code point)對應(yīng)的一個(gè)字符的表。
該表用于賦予 byte 意義。還需要知道一個(gè)點(diǎn):因?yàn)?ASCII 字符集支持的字符太少,不能表示各個(gè)國家語言中的字符。所以就發(fā)明了
Unicode ——萬國碼,該字符集包含了你能用到的所有的字符。
1.2 Encode / Decode
在 python 中字符串分為兩個(gè)對象:str 和 unicode
str: a sequence of bytes
unicode:a sequence of code point(碼位——字符集中的數(shù)字)
unicode_obj.encode() ——> bytes ‘編碼’(encode)
bytes_obj.decode() ——> unicode ‘解碼’(decode)
UTF-8 是最流行的一種對 Unicode 進(jìn)行傳播和存儲(chǔ)的編碼方式。所以,多用它作為編碼方式。
s = 'hello' # str
u = u'你好' # unicode
back_to_bytes = u.encode('utf-8')
back_to_utf8 = back_to_bytes.decode('utf-8') # 或 unicode(s, 'utf-8')
1.3 聲明編碼
正如前面所說的,計(jì)算機(jī)只能操作 bytes,所以 Python 在編譯原文件的時(shí)候,會(huì)先把源文件進(jìn)行編碼,默認(rèn)以‘ASCII’進(jìn)行編碼。這就是為什么如果源文件中帶有‘中文’,需要在源文件的起始行聲明編碼方式。
完成編碼后,源碼中的所有字符,都變成了 bytes 計(jì)算機(jī)就可以進(jìn)行編譯和處理了。編譯過程:
讀取文件
不同的文件,根據(jù)其聲明的編碼去解析為Unicode
轉(zhuǎn)換為UTF-8字符串
針對UTF-8字符串,去分詞
編譯,創(chuàng)建Unicode對象(Python解釋器處理)
根據(jù)這個(gè)過程,在自己的代碼中也應(yīng)該按照這個(gè)邏輯處理,意思是:
接收外部數(shù)據(jù)時(shí),統(tǒng)一轉(zhuǎn)化為Unicode
代碼內(nèi)部處理的都是Unicode
輸出時(shí)統(tǒng)一轉(zhuǎn)化為UTF-8(網(wǎng)絡(luò)數(shù)據(jù)傳輸、文本輸出)
1.4 小結(jié)
程序中所有的輸入和輸出均為 byte
世界上的文本需要比 256 更多的符號(hào)來表現(xiàn)(ASCII是不夠的)
你的程序必須能夠處理 byte 和 unicode
byte 流中不會(huì)包含編碼信息(編碼信息會(huì)在:文件的開頭、協(xié)議中等地方聲明)Content-Type:text/html; charset=UTF-8
指明的編碼有可能是錯(cuò)誤的(出現(xiàn)亂碼)
2、python “幫”你做的事情
在 python 中處理編碼問題,會(huì)出現(xiàn)很多問題,這里就不一一列舉。
這些問題大都是使用了不匹配的編碼方式進(jìn)行解碼、編碼造成的。而 python 為了語法更加簡介,在一些內(nèi)置方法中,使用了一些隱性轉(zhuǎn)換。這種隱形的轉(zhuǎn)換帶了的便捷的同時(shí)也會(huì)帶來一些非預(yù)期的錯(cuò)誤。下面就一一道來。
2.1 a = "abc" + u"bcd"
a = "abc" + u"bcd",Python 會(huì)如此轉(zhuǎn)換 "abc".decode(sys.getdefaultencoding()) 然后將兩個(gè) Unicode 字符合并。
2.2 兩個(gè)內(nèi)建方法str()和unicode(),
str:something.encode(sys.getdefaultencoding())
unicode:something.decode(sys.getdefaultencoding())
sys.getdefaultencoding()默認(rèn)為:ASCII,這就是為什么str(u'中文')和unicode('中文')分別會(huì)報(bào)錯(cuò):UnicodeEncodeError和UnicodeDecodeError。因?yàn)锳SCII編碼方式,編碼/解碼不了中文(支持的字符有限)。
2.3 print函數(shù)
print函數(shù),會(huì)對輸出的內(nèi)容進(jìn)行編碼,這是因?yàn)?#xff1a;所謂的輸出,也是從一個(gè)程序到另外一個(gè)程序。程序之間的交互都是都是傳遞 bytes。比方說print,就是把數(shù)據(jù)傳遞給 終端 ,終端也是個(gè)程序,所以print函數(shù)就把需要輸出的內(nèi)容編碼成了 bytes,采用那種編碼方式,就是
由sys.stdout.encoding參數(shù)決定的。
在交互環(huán)境下(python、ipython)輸入的數(shù)據(jù)的編碼則由sys.stdin.encoding參數(shù)決定。參考:What does python print() function actually do?
2.4 默認(rèn)編碼方式
python 的默認(rèn)編發(fā)方式為 ASCII。
如何改變python的默認(rèn)編碼方式?:
import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys) # Reload does the trick!
sys.setdefaultencoding('UTF8')
為什么要重載sys模塊?
因?yàn)槿绻诰幾g.py文件的之前,改變默認(rèn)編碼,會(huì)影響Python的編譯。
當(dāng)編譯完,再重載sys模塊,它就是變成了第三方模塊,可以隨便更改,不回影響編譯。setdefaultencoding()函數(shù)才可以調(diào)用。參考:Changing default encoding of Python?
3、推薦姿勢
本片文章沒有列舉出常見的異常,因?yàn)槿绻炊松厦嫠械慕忉?。再按照下面的姿勢使?#xff0c;那么 python2 中的編碼問題,因該就不會(huì)再困擾你了。
Unicode 三明治:盡可能的讓你程序處理的文本都為 Unicode 。如下圖:
了解你的字符串。你應(yīng)該知道你的程序中,哪些是 unicode, 哪些是 byte,對于這些 byte 串。你應(yīng)該知道,他們的編碼是什么。(詳情見上述小結(jié)第 4 條)
測試 Unicode 支持。使用一些奇怪的符號(hào)來測試你是否已經(jīng)做到了以上幾點(diǎn)。(測試看看你的程序是否支持中文)
參考
本文同步分享在 博客"削微寒的程序員之路"(CNBlog)。
如有侵權(quán),請聯(lián)系 support@oschina.cn 刪除。
本文參與“OSC源創(chuàng)計(jì)劃”,歡迎正在閱讀的你也加入,一起分享。
總結(jié)
以上是生活随笔為你收集整理的python2编码问题解决了吗_Python2编码问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WBE前端笔记1:HTML中一些不熟悉的
- 下一篇: Python3——FTP(文件传输协议)