在講述fileinput模塊之前,首先說一下python內置的文件API—open()函數以及與其相關的函數。 我這裡主要講講其中四個比較重要和常用的方法,更多的方法,可以參考:菜鳥教程http://www.runoob.com/python/file-methods.html (1)file = ...
在講述fileinput模塊之前,首先說一下python內置的文件API—open()函數以及與其相關的函數。
我這裡主要講講其中四個比較重要和常用的方法,更多的方法,可以參考:菜鳥教程http://www.runoob.com/python/file-methods.html
(1)file = open(file_name [, access_mode][, buffering])
參數解析:
1. file_name:
file_name變數是一個需要訪問的文件名稱的字元串值,在應用中需要用單引號或者雙引號將文件名包裹起來。
2. access_mode:
access_mode決定了打開文件的模式:只讀,寫入,追加等。這個參數是非強制的,預設文件訪問模式為只讀(r)
詳細模式可以參考:菜鳥教程http://www.runoob.com/python/python-files-io.html
3. buffering:
這個參數用於設置緩存區的大小。如果buffering的值被設為0,就不會有緩存。如果buffering的值取1,訪問文件時會寄存行。如果將buffering的值設為大於1的整數,這個整數就為緩存區的緩存大小。如果取負值,寄存區的緩衝大小則為系統預設。
(2)file.flush()方法
用於刷新緩衝區,,即將緩衝區中的數據立刻寫入文件,同時清空緩衝區
flush()方法在爬蟲中也用得挺多,在爬蟲過程由於種種原因,程式中斷,寫入緩存的數據沒有寫入磁碟很可惜,所以可以手動添加flush()方法
(3)file.close()方法
關閉文件,並將緩衝區的數據寫入文件中。
文件的緩存機制
在寫入文件內容的時候,在我們調用python的write()函數對文件進行寫入的時候,python解析器會調用操作系統的write方法,但值得註意的是,不是馬上保存到磁碟中的,是先寫到內核的緩衝區裡面,只有當我們主動調用flush()函數或者close()函數的時候,才會將緩衝區的內容寫入磁碟中。另外當寫入的數據量大於或者等於緩衝區的大小的時候,寫緩衝會自動同步到磁碟。
例如:
寫20萬行數據結果
file = open('file1.txt','a+') for i in range(200000): file.write('this line is line%s'%i) file.write('\r\n')
pycharm報出如下的提示
因為我設置的buffering是預設的系統的緩存大小,所以當寫到1999856行時,就剛好到系統的緩存區大小,因為所需要寫的數據大於緩存區的大小,所以這些內容直接就寫入了磁碟,而1998856後面的數據在寫入的時候還是先寫到了緩存區中,而這些數據的大小顯然是小於緩存區大小的,所以被保存在緩存區中,並沒有寫到磁碟。
使用flush()方法後,所有在緩存區的數據都會寫入到磁碟中
如果我直接在調用open()方法的時候像下麵這樣設置buffering為1,就無需擔心緩存的問題了
(4)file.seek(offset [,whence]) 文件指針
當文件進行寫入或者讀取的時候,文件指針會根據具體的內容進行移動。靈活地運用seek()方法,可以在一次I/O操作中對文件同時進行寫和讀操作,避免多次的I/O。
參數解析:
offset:偏移量,代表需要移動偏移的位元組數
whence:可選參數,預設值為 0。作用是給offset參數設定起始值,表示要從哪個位置開始偏移。0代表從文件開頭開始算起,1代表從當前位置開始算起,2代表從文件末尾算起。
例如以下案例:
file = open('file.txt','a+',1) for i in range(200): file.write('this line is line%s'%i) file.write('\r\n') for line in file: print(line) file.close()
終端沒有列印任何數據
如果將代碼順序修改一下
file = open('file.txt','a+',1) for i in range(200): file.write('this line is line%s'%i) file.write('\r\n') file.close() f = open('file.txt','r+') for line in f: print(line) f.close()
終端列印出數據
那麼怎麼用seek()方法呢?
import os file = open('file.txt','a+',1) for i in range(200): file.write('this line is line%s'%i) file.write('\r\n') file.seek(0,os.SEEK_SET) for line in file: print(line) file.close()
同樣也能列印出數據
上面,我用了os模塊的SEEK_SET
os模塊有這些內容:
os.SEEK_SET:表示文件的相對起始位置
os.SEEK_CUR:表示文件的相對當前位置
os.SEEK_END:表示文件的相對結束位置
關於fileinput模塊
fileinput可以對文件進行細緻化的處理,比直接的open方法有更多文件操擴展。可以一次性迭代一個或者多個文件,並對文件進行修改。
主要的函數有:
1. input([files[,inplace[,backup]]]) 幫助迭代多個輸入流中的行
2. filename() 返回當前文件的名稱
3.nestfile() 關閉當前文件並移動到下一個文件
4. close() 關閉序列(多個文件
5. lineno() 返回(多個文件累計的)當前行號
6. filelineno() 返回在當前文件的行好
7. isfirstline() 檢查當前是否是當前文件中的第一行
8. isstdin() 檢查最後一行是否來自sys.stdin
可以理解,fileinput模塊重點是對多文件的讀取和適當時候的修改。而沒有直接的寫操作
1. input()方法
這個函數是fileinput模塊中最重要的一個函數,參數相對複雜一點。
官方的定義:
fileinput.input([files[, inplace[, backup[, bufsize[, mode[, openhook]]]]]])
input(files=None, inplace=False, backup='', bufsize=0, mode='r', openhook=None)
1)files列表,可以是一個文件,也可以是多個文件的列表形式
2)inplace 是否對文件進行就地修改。預設為False,設置為False跟文件的open區別不大
3)mode 讀取的格式
官方:FileInput opening mode must be one of 'r', 'rU', 'U' and 'rb' (b:二進位位元組模式和U:unicode模式)
4)backup 文件備份,為原本的文件做一份備份,不作任何修改,其實就是複製。備份的文件名是原本的文件名+備份文件名。註意備份文件需要把文件的格式也寫進去。一般backup需要與參數inplace一起使用才有意義。而在設置了inplace=True,一般同時會設置backup參數來備份原本的文件內容。
例子:在每一行文本的前面添加 ‘#行號’字樣
單個文件案例:
for line in fileinput.input('file.txt',inplace=True,mode='r',backup='file_back.txt'): num = fileinput.filelineno() print('#%s'%num+' '+line)
如果inplace設置為True,即就地修改,必須要有print函數將讀取的數據重新寫回當前的文件中,否則文件的數據最後會變成空。所以使用inplace時候必須很小心。
備份後的文件目錄
多個文件案例
for line in fileinput.input(files=['file.txt','file1.txt'],inplace=True,mode='r',backup='file_back.txt'):
num = fileinput.filelineno()
print('#%s'%num+' '+line
通常fileinput模塊會結合re模塊一起使用,例如在對日誌的分析中會很有用
例如,這裡有一個monoodb的log文件內容
希望獲取日期為11-13的日誌
import fileinput import re for line in fileinput.input('mongolog.txt',mode='r',inplace=True,backup='log_backup.txt'): pattern = '2018-11-13' if re.search(pattern,line): print(line)
獲取結果在原log.txt文件中,備份文件中的內容與原文件相同