淺析Python解析器解析全過程
首先先讓大家看一下Python解析器的全流程:我們先用編輯器編寫好源代碼,保存成文件。如果源代碼中有編碼聲明而且用的編輯器支持該語法,那么該文件就以相應(yīng)的編碼方式保存在磁盤中。
注意: 編碼聲明和源文件的編碼不一定是一致的,你完全可以在編碼聲明中聲明編碼為UTF-8,但是用GB2312來保存源文件。當(dāng)然,我們不可能自尋煩惱,故意寫錯,而且好的IDE也能強制保證兩者的一致性,但是,如果我們用記事本或者EditPlus等編輯器來編寫代碼的話,一不小心就會出現(xiàn)這種問題的。
得到一個.py文件后,我們就可以運行它了,這是,我們就把代碼交給Python解析器來完成解析工作。解析器讀入文件時,先解析文件中的編碼聲明,我們假設(shè)文件的編碼為gb2312,那么先將文件中的內(nèi)容由gb2312轉(zhuǎn)換成Unicode,然后再把這些Unicode轉(zhuǎn)換為UTF-8格式的字節(jié)串。
(注:這里僅指源代碼即腳本代碼的純代碼轉(zhuǎn)換) 完成這一步驟后,解析器把這些UTF-8字節(jié)串分段,解析。如果遇到使用Unicode字符串(注:比如遇到 u'中國a我愛你') ,那么就使用相應(yīng)的UTF-8字節(jié)串創(chuàng)建Unicode字符串。
如果程序中使用的是一般的字符串,那么解析器先將UTF-8字節(jié)串通過Unicode轉(zhuǎn)換成相應(yīng)編碼(這里就是gb2312編碼)的字節(jié)串(注:普通的,非unicode的,即ascii ),并用其創(chuàng)建一般的字符串對象。也就是說,Unicode字符串跟一般字符串在內(nèi)存中的存放格式是不一樣的,前者使用UTF-8的格式,后者使用GB2312格式。
好了,內(nèi)存中的字符串存放格式我們知道了,下面我們要了解print的工作方式。print其實只是負責(zé)把內(nèi)存中相應(yīng)的字節(jié)串交給操作系統(tǒng),讓操作系統(tǒng)相應(yīng)的程序(譬如cmd窗口)進行顯示。這里有兩種情況:
1、若字符串是一般的字符串,那么print只需把內(nèi)存中相應(yīng)的字節(jié)串推送給操作系統(tǒng)。如例子中的code 1。
2、如果字符串是Unicode字符串,那么print在推送之前先進行相應(yīng)的encode:我們可以顯示使用Unicode的encode方法使用合適的編碼方式來編碼(例子中code 2)
否則Python使用默認的編碼方式進行編碼,也就是ASCII(例子中的code 3)。當(dāng)然ASCII是不可能正確編碼中文的,因此Python報錯。至此,上面的三個問題我們已經(jīng)可以解析***和第三個了。至于第二個問題,因為Python中有兩種字符串,一般字符串和Unicode字符串,兩者都有各自的字符處理方法。
對于前者,方法是以字節(jié)的方式進行的,而且在GB2312中,每個漢字占用兩個字節(jié),因此得到的結(jié)果是5;對于后者,也就是 Unicode字符串,所有字符都是統(tǒng)一看待的,因此得到。
雖然上面只提到了控制臺程序的中文問題,但是文件讀寫以及網(wǎng)絡(luò)傳輸中出現(xiàn)的中文問題在原理上都是類似的。Unicode的出現(xiàn)可以很大程度上解決軟件的國際化問題,同時Python為Unicode提供了極為良好的支持,因此,我建議大家在編寫Python的程序時,都統(tǒng)一使用Unicode方式。
保存文件時使用UTF-8的編碼方式。How to Use UTF-8 with Python有詳細的描述,大家可以參考一下。Python中能導(dǎo)致出現(xiàn)中文問題的地方還很多,譬如文件的讀寫,網(wǎng)絡(luò)數(shù)據(jù)的傳輸?shù)?,希望大家能多多交流,共同解決這些問題。
回顧一下使用Python解析器的流程:首先,先用編輯器編寫好源代碼,保存成文件。如果源代碼中有編碼聲明而且用的編輯器支持該語法,那么該文件就以相應(yīng)的編碼方式保存在磁盤中。注意:編碼聲明和源文件的編碼不一定是一致的,完全可以在編碼聲明中聲明編碼為UTF-8,但是用GB2312來保存源文件。
當(dāng)然,這是自尋煩惱,而且好的IDE也應(yīng)該保證兩者的一致性。但是,如果。用記事本或者EditPlus等編輯器來編寫代碼的話,可能就會出現(xiàn)這種問題的。得到一個.py文件后,可以運行它。這是把代碼交給Python解析器來完成解析工作。解析器讀入文件時,先解析文件中的編碼聲明,假設(shè)文件的編碼為gb2312。
那么先將文件中的內(nèi)容由gb2312轉(zhuǎn)換成Unicode,然后再把這些Unicode轉(zhuǎn)換為UTF-8格式的字節(jié)串。完成這一步驟后,解析器把這些UTF-8字節(jié)串分段,解析。如果遇到使用Unicode字符串,那么就使用相應(yīng)的UTF-8字節(jié)串創(chuàng)建Unicode字符串,如果程序中使用的是一般的字符串。
那么解析器先將UTF-8字節(jié)串通過Unicode轉(zhuǎn)換成相應(yīng)編碼(這里就是gb2312編碼)的字節(jié)串,并用其創(chuàng)建一般的字符串對象。也就是說,Unicode字符串跟一般字符串在內(nèi)存中的存放格式是不一樣的,前者使用UTF-8的格式,后者使用GB2312格式。
【編輯推薦】