Python 2 Tutorial 第一堂(4)Unicode 支援、基本I/O
文章推薦指數: 80 %
# coding=UTF-8 filename = raw_input('檔名:') f = open(filename, 'r') b_str = f.read() f.close() print b_str.decode('utf-8') # 這是什麼? print ...
回PythonTutorial
在第一堂下課之前,來談談練習2:哈囉!世界! 做了什麼?為了方便,把範例程式碼再貼過來一下:
#coding=UTF-8
filename=raw_input('檔名:')
f=open(filename,'r')
b_str=f.read()
f.close()
printb_str.decode('utf-8')#這是什麼?
printb_str.decode('utf-8').encode('utf-8')#這是什麼?
Python的Unicode支援
第1行是 編碼宣告(Encodingdeclaration),這是個魔法註解(Magiccomment),它告訴Python直譯器,這個原始碼檔案是以UTF-8來編碼,如果不這麼加上這個魔法註解,Python2.x會以ASCII編碼來解讀原始碼,那麼就會出現以下錯誤:
SyntaxError:Non-ASCIIcharacter'\xe6'infilehello.pyonline1,butnoencodingdeclared;seehttp://www.python.org/peps/pep-0263.htmlfordetails
魔法註解中設定了UTF-8,這是因為在Ubuntu12.04LTS中,預設採用的文字編碼是UTF-8。
有趣的是,有時我上課會問學員一個問題:「你用的原始碼文字編碼是什麼?」很多學員答不出來,很多人不知道自己作業系統中開個純文字檔編碼是什麼,不知道在整合開發環境(IntegratedDevelopmentEnvironment,IDE)中開個原始碼編碼是什麼,當然也就不知道為什麼把A專案的原始碼放到B專案中程式碼會出現亂碼。
如果你連UTF-8是什麼都不知道,那建議你看看我寫的亂碼1/2中這幾篇文件:
哪來的純文字檔?
Unicode與UTF
UTF-8
在Python2.x,程式中所有文字都是 str的實例,可以視為代表文字資料的位元組序列(Bytesequence)。
例如在Python中,可以使用len函式來取得序列長度,不過以下的程式會顯示6,即使'測試'是兩個字元:
#coding=UTF-8
text='測試'
printlen(text)#顯示6
這是因為'測試'這兩個字元,使用UTF-8編碼的話,會使用六個位元組,len函式實際上是計算位元組序列的長度,而不是字元長度。
在Python2.x中,如果想要用Unicode來代表文字,也就是想要用 unicode型態來封裝文字,可以使用Unicode字面常量(Unicodeliteral)來表示,也就是在文字前置一個u符號。
例如:
#coding=UTF-8
text=u'測試'
printtype(text)#顯示"
除了使用Unicode字面常量來建立unicode實例外,在Python2.x中,如果有個str的實例,可以使用其decode方法,指定str的實例代表何種編碼的位元組序列,這樣就可以傳回文字的unicode實例。
相反地,如果使用unicode實例的encode方法,可指定編碼取得文字實際編碼後的位元組序列。
在Python3.x中,預設原始碼檔案必須是UTF-8編碼。
如果原始碼檔案想要是UTF-8以外的編碼,同樣必須在第1行放置編碼宣告。
Python3.x中,文字是str型態的實例,不過str代表的是Unicode(而不是像Python2.x代表的是位元組序列),下面這個程式在Python3.x中執行的話:
text='測試'
print(type(text))#顯示"
如果想取得文字實際編碼後的位元組序列,可以使用encode方法指定編碼,這會傳回一個bytes實例,如果有個bytes實例,可以使用decode指定編碼,傳回代表Unicode的str實例。
例如下圖是在Python3.x互動交談環境中的測試實例:
如果想知道更多Python中有關文字編碼的細節,可以再參考 Python的編碼這篇文件。
基本 I/O
接下來看看有關基本I/O的部份,你可以使用open函式來開啟檔案,開啟時指定存取模式,'r'表示讀取,'w'表示寫入,open函式會傳回file實例,使用read方法可以讀取檔案內容,以str型態傳回,如先前談到,傳回的str實際上代表著位元組序列。
以下是個實際的讀取程式範例:
importsys
file=open(sys.argv[1],'r')
content=file.read()
printcontent
file.close()
程式第一行匯入(import)了sys模組,sys.argv是個list,其中儲存了執行程式時的命令列引數(Commandlinearguments),索引0固定都是執行時的模組名稱,而後是跟隨著的引數,例如執行pythonhello.pyonetwothree時,sys.argv[0]就會是'hello.py',其餘索引則是'one'、'two'、'three'。
print在Python2.x中是個陳述句,用來顯示指定的資料,不使用檔案時,記得使用close關閉檔案。
類似地,一個寫入檔案的程式範例如下,write方法會將文字的位元組序列寫入至檔案中:
importsys
file=open(sys.argv[1],'w')
file.write('test')
file.close()
如果要逐行讀取檔案呢?可以使用file的readline方法,例如逐行讀取一個文字檔案的所有內容,可以在while迴圈中進行:
importsys
file=open(sys.argv[1],'r')
whileTrue:
line=file.readline()
ifnotline:break
printline
file.close()
如果讀不到東西了,那readline會傳回'',在if判斷式中,''會被視為False。
while後加上:表示區塊開始,Python中使用縮排來決定區塊範圍。
注意!你可以自行決定縮排字元,但是Python中縮排要一致,如果縮排想使用Tab字元,那所有原始碼就都要使用Tab字元縮排,如果要使用四個空白字元,那所有原始碼就得是四個空白字元來縮排,強制統一縮排,是Python的特色,也是Python的文化。
可以使用file的readlines方法一次讀取所有檔案內容,這會傳回list,每個索引處代表一行內容,一個程式範例是這樣的:
importsys
file=open(sys.argv[1],'r')
forlineinfile.readlines():
printline
file.close()
forin語法可作用在list上,逐一取出list中的元素並指定給變數,對於forlineinfile.readlines()是這樣閱讀的:對於file.readlines()傳回的list中每個元素,將之指定給line。
實際上對於Python來說,讀取檔案最好的方式,就是不要去read它,這是什麼意思?是這樣的…
importsys
forlineinopen(sys.argv[1],'r'):
printline
這是Python的風格,也是Python的文化,這樣的寫法好處就是增加了可讀性,你不用自行使用close關閉檔案,這個語法會在forin結束後自行關閉檔案在file實例被回收後,檔案就會關閉,forlineinopen(sys.argv[1],'r')是這樣閱讀的:對於開啟檔案的每一行。
除了可讀性外,這個語法還能讓讀取更有效率,不過現階段你不用管這些事,只要當這語法背後施了些魔法就好。
整合開發工具
真正開發程式時,你也許會想要使用整合開發工具,在Python的世界中,我確實花了些時間去瞭解有沒有主流的整合開發工具,不過事後覺得,在Python的世界中,除了團隊因素決定之外,更多時候是個人口味問題,基於課程時間,我就不逐一討論我調查過的那些工具特色為何了,以下列出一些課程前調查過的幾個:
PyCharm/IntelliJIDEA
PyDev/Eclipseplugin
KomodoIDE
Spyder
WingIDE
NINJA-IDE
PythonToolsforVisualStudio
實際上似乎是如此,在Python社群中也有過這樣的一條討論:
有沒有好的PythonIDE呢?
第一堂課的內容就到這邊了,我們認識了Python環境的安裝與準備,寫了第一個Python程式,瞭解了一些Unicode支援,並看了些基本的I/O,休息一下!後面要來進入第二堂課,瞭解更多Python語言的細節。
參考資源
直譯器的選擇與安裝
http://www.python.org/download/releases/3.0/
http://www.python.org/download/releases/2.7.3/
http://docs.python-guide.org/en/latest/starting/which-python/
準備課程環境
http://docs.python-guide.org/en/latest/starting/install/linux/
程式庫在哪呢?
http://docs.python.org/2/using/cmdline.html
Distutils、Distribute與Pip間的關係
http://docs.python.org/2/library/distutils.html
http://pypi.python.org/pypi/distribute
http://pypi.python.org/pypi/pip
http://blog.yangyubo.com/2012/07/27/python-packaging/
http://www.openfoundry.org/tw/tech-column/8536-introduction-of-python-extension-management-tools
哈囉!世界!
https://openhome.cc/Gossip/Python/IOABC.html
https://openhome.cc/Gossip/Encoding/
https://openhome.cc/Gossip/Encoding/Python.html
延伸文章資訊
- 1A Guide to Unicode, UTF-8 and Strings in Python
A good practice is to decode your bytes in UTF-8 (or an encoder that was used to create those byt...
- 2Day27 Python 基礎- 字符轉編碼操作 - iT 邦幫忙
ASCII 只能儲英文或特殊字符,只占一個字節,一個字節8bit,不能儲中文,所以才出現Unicode. Unicode 不管是中文或英文,都是占二個字節,一個字節8bit. UTF-8 是一種...
- 3Python 2 Tutorial 第一堂(4)Unicode 支援、基本I/O
# coding=UTF-8 filename = raw_input('檔名:') f = open(filename, 'r') b_str = f.read() f.close() pri...
- 4How to Convert a String to UTF-8 in Python? - Studytonight
UTF is “Unicode Transformation Format” , and '8' means 8-bit values are used in the encoding. It ...
- 5Python 的編碼
py 檔案想要是UTF-8 以外的編碼,同樣必須在第一行放置編碼聲明。 # coding=Big5 text = '測試' print( ...