文件,是 computer 姑娘中非常重要的東西,在 Python 里,它也是一種類型的對(duì)象,類似前面已經(jīng)學(xué)習(xí)過的其它數(shù)據(jù)類型,包括文本的、圖片的、音頻的、視頻的等等,還有不少?zèng)]見過的擴(kuò)展名的。事實(shí)上,在 linux 操作系統(tǒng)中,所有的東西都被保存到文件中。
先在交互模式下查看一下文件都有哪些屬性:
>>> dir(file)
['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']
然后對(duì)部分屬性進(jìn)行詳細(xì)說明,就是看官學(xué)習(xí)了。
特別注意觀察,在上面有__iter__這個(gè)東西。曾經(jīng)在講述列表的時(shí)候,是不是也出現(xiàn)這個(gè)東西了呢?是的。它意味著這種類型的數(shù)據(jù)是可迭代的(iterable)。在下面的講解中,你就會(huì)看到了,能夠用 for 來讀取其中的內(nèi)容。
在某個(gè)文件夾下面建立了一個(gè)文件,名曰:130.txt,并且在里面輸入了如下內(nèi)容:
learn python
http://qiwsir.github.io
qiwsir@gmail.com
此文件一共三行。
下圖顯示了這個(gè)文件的存儲(chǔ)位置:
http://wiki.jikexueyuan.com/project/start-learning-python/images/12601.png" alt="" />
在上面截圖中,我在當(dāng)前位置輸入了 Python(我已經(jīng)設(shè)置了環(huán)境變量,如果你沒有,需要寫全啟動(dòng) Python 命令路徑),進(jìn)入到交互模式。在這個(gè)交互模式下,這樣操作:
>>> f = open("130.txt") #打開已經(jīng)存在的文件
>>> for line in f:
... print line
...
learn Python
http://qiwsir.github.io
qiwsir@gmail.com
提醒初學(xué)者注意,在那個(gè)文件夾輸入了啟動(dòng) Python 交互模式的命令,那么,如果按照上面的方法 open("130.txt")打開文件,就意味著這個(gè)文件 130.txt 是在當(dāng)前文件夾內(nèi)的。如果要打開其它文件夾內(nèi)的文件,請用相對(duì)路徑或者絕對(duì)路徑來表示,從而讓 python 能夠找到那個(gè)文件。
將打開的文件,賦值給變量 f,這樣也就是變量 f 跟對(duì)象文件 130.txt 用線連起來了(對(duì)象引用),本質(zhì)上跟前面所講述的其它類型數(shù)據(jù)進(jìn)行賦值是一樣的。
接下來,用 for 來讀取文件中的內(nèi)容,就如同讀取一個(gè)前面已經(jīng)學(xué)過的序列對(duì)象一樣,如 list、str、tuple,把讀到的文件中的每行,賦值給變量 line。也可以理解為,for 循環(huán)是一行一行地讀取文件內(nèi)容。每次掃描一行,遇到行結(jié)束符號(hào) \n 表示本行結(jié)束,然后是下一行。
從打印的結(jié)果看出,每一行跟前面看到的文件內(nèi)容中的每一行是一樣的。只是行與行之間多了一空行,前面顯示文章內(nèi)容的時(shí)候,沒有這個(gè)空行?;蛟S這無關(guān)緊要,但是,還要深究一下,才能豁然。
在原文中,每行結(jié)束有本行結(jié)束符號(hào) \n,表示換行。在 for 語句匯總,print line 表示每次打印完 line 的對(duì)象之后,就換行,也就是打印完 line 的對(duì)象之后會(huì)增加一個(gè) \n。這樣看來,在每行末尾就有兩個(gè) \n,即:\n\n,于是在打印中就出現(xiàn)了一個(gè)空行。
>>> f = open('130.txt')
>>> for line in f:
... print line, #后面加一個(gè)逗號(hào),就去掉了原來默認(rèn)增加的 \n 了,看看,少了空行。
...
learn Python
http://qiwsir.github.io
qiwsir@gmail.com
在進(jìn)行上述操作的時(shí)候,有沒有遇到這樣的情況呢?
>>> f = open('130.txt')
>>> for line in f:
... print line,
...
learn Python
http://qiwsir.github.io
qiwsir@gmail.com
>>> for line2 in f: #在前面通過 for 循環(huán)讀取了文件內(nèi)容之后,再次讀取,
... print line2 #然后打印,結(jié)果就什么也顯示,這是什么問題?
...
>>>
如果看官?zèng)]有遇到上面問題,可以試試。這不是什么錯(cuò)誤,是因?yàn)榍耙淮我呀?jīng)讀取了文件內(nèi)容,并且到了文件的末尾了。再重復(fù)操作,就是從末尾開始繼續(xù)讀了。當(dāng)然顯示不了什么東西,但是 Python 并不認(rèn)為這是錯(cuò)誤,因?yàn)楹竺婢蜁?huì)講到,或許在這次讀取之前,已經(jīng)又向文件中追加內(nèi)容了。那么,如果要再次讀取怎么辦?就從新來一邊好了。這就好比有一個(gè)指針在指著文件中的每一行,每讀完一行,指針向移動(dòng)一行。直到指針指向了文件的最末尾。當(dāng)然,也有辦法把指針移動(dòng)到任何位置。
特別提醒看官,因?yàn)楫?dāng)前的交互模式是在該文件所在目錄啟動(dòng)的,所以,就相當(dāng)于這個(gè)實(shí)驗(yàn)室和文件 130.txt 是同一個(gè)目錄,這時(shí)候我們打開文件 130.txt,就認(rèn)為是在本目錄中打開,如果文件不是在本目錄中,需要寫清楚路徑。
比如:在上一級(jí)目錄中(~/Documents/ITArticles/BasicPython),假如我進(jìn)入到那個(gè)目錄中,運(yùn)行交互模式,然后試圖打開 130.txt 文件。
http://wiki.jikexueyuan.com/project/start-learning-python/images/12602.png" alt="" />
>>> f = open("130.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: '130.txt'
>>> f = open("./codes/130.txt") #必須得寫上路徑了(注意,windows的 路徑是 \ 隔開,需要轉(zhuǎn)義。對(duì)轉(zhuǎn)義符,看官看以前講座)
>>> for line in f:
... print line
...
learn Python
http://qiwsir.github.io
qiwsir@gmail.com
>>>
上面的實(shí)驗(yàn)中,打開的是一個(gè)已經(jīng)存在的文件。如何創(chuàng)建文件呢?
>>> nf = open("131.txt","w")
>>> nf.write("This is a file")
就這樣創(chuàng)建了一個(gè)文件?并寫入了文件內(nèi)容呢?看看再說:
http://wiki.jikexueyuan.com/project/start-learning-python/images/12603.png" alt="" />
真的就這樣創(chuàng)建了新文件,并且里面有那句話呢。
看官注意了沒有,這次我們同樣是用 open() 這個(gè)函數(shù),但是多了個(gè)"w",這是在告訴 Python 用什么樣的模式打開文件。也就是說,用 open() 打開文件,可以有不同的模式打開??聪卤恚?/p>
| 模式 | 描述 |
|---|---|
| r | 以讀方式打開文件,可讀取文件信息。 |
| w | 以寫方式打開文件,可向文件寫入信息。如文件存在,則清空該文件,再寫入新內(nèi)容 |
| a | 以追加模式打開文件(即一打開文件,文件指針自動(dòng)移到文件末尾),如果文件不存在則創(chuàng)建 |
| r+ | 以讀寫方式打開文件,可對(duì)文件進(jìn)行讀和寫操作。 |
| w+ | 消除文件內(nèi)容,然后以讀寫方式打開文件。 |
| a+ | 以讀寫方式打開文件,并把文件指針移到文件尾。 |
| b | 以二進(jìn)制模式打開文件,而不是以文本模式。該模式只對(duì) Windows 或 Dos 有效,類 Unix 的文件是用二進(jìn)制模式進(jìn)行操作的。 |
從表中不難看出,不同模式下打開文件,可以進(jìn)行相關(guān)的讀寫。那么,如果什么模式都不寫,像前面那樣呢?那樣就是默認(rèn)為 r 模式,只讀的方式打開文件。
>>> f = open("130.txt")
>>> f
<open file '130.txt', mode 'r' at 0xb7530230>
>>> f = open("130.txt","r")
>>> f
<open file '130.txt', mode 'r' at 0xb750a700>
可以用這種方式查看當(dāng)前打開的文件是采用什么模式的,上面顯示,兩種模式是一樣的效果,如果不寫那個(gè)"r",就默認(rèn)為是只讀模式了。下面逐個(gè)對(duì)各種模式進(jìn)行解釋
"w":以寫方式打開文件,可向文件寫入信息。如文件存在,則清空該文件,再寫入新內(nèi)容
131.txt 這個(gè)文件是存在的,前面建立的,并且在里面寫了一句話:This is a file
>>> fp = open("131.txt")
>>> for line in fp: #原來這個(gè)文件里面的內(nèi)容
... print line
...
This is a file
>>> fp = open("131.txt","w") #這時(shí)候再看看這個(gè)文件,里面還有什么呢?是不是空了呢?
>>> fp.write("My name is qiwsir.\nMy website is qiwsir.github.io") #再查看內(nèi)容
>>> fp.close()
查看文件內(nèi)容:
$ cat 131.txt #cat 是 linux 下顯示文件內(nèi)容的命令,這里就是要顯示 131.txt 內(nèi)容
My name is qiwsir.
My website is qiwsir.github.io
"a":以追加模式打開文件(即一打開文件,文件指針自動(dòng)移到文件末尾),如果文件不存在則創(chuàng)建
>>> fp = open("131.txt","a")
>>> fp.write("\nAha,I like program\n") #向文件中追加
>>> fp.close() #這是關(guān)閉文件,一定要養(yǎng)成一個(gè)習(xí)慣,寫完內(nèi)容之后就關(guān)閉
查看文件內(nèi)容:
$ cat 131.txt
My name is qiwsir.
My website is qiwsir.github.io
Aha,I like program
其它項(xiàng)目就不一一講述了??垂倏梢宰约簩?shí)驗(yàn)。
在對(duì)文件進(jìn)行寫入操作之后,一定要牢記一個(gè)事情:file.close(),這個(gè)操作千萬不要忘記,忘記了怎么辦,那就補(bǔ)上吧,也沒有什么天塌地陷的后果。
有另外一種方法,能夠不用這么讓人揪心,實(shí)現(xiàn)安全地關(guān)閉文件。
>>> with open("130.txt","a") as f:
... f.write("\nThis is about 'with...as...'")
...
>>> with open("130.txt","r") as f:
... print f.read()
...
learn python
http://qiwsir.github.io
qiwsir@gmail.com
hello
This is about 'with...as...'
>>>
這里就不用 close()了。而且這種方法更有 Python 味道,或者說是更符合 Pythonic 的一個(gè)要求。
總目錄 | 上節(jié):語句(5) | 下節(jié):文件(2)
如果你認(rèn)為有必要打賞我,請通過支付寶:qiwsir@126.com,不勝感激。