1. 程式人生 > Python進階應用教學 >23 Python 中的檔案 IO 操作

23 Python 中的檔案 IO 操作

1. 開啟和關閉檔案

1.1 開啟檔案

訪問檔案前,需要使用用 Python 內建的 open() 函式開啟一個檔案:

open(path, access_mode)
  • path 是要訪問的檔案的路徑名
  • access_mode 是檔案的訪問模式
    • 可以是隻讀、讀寫、追加等模式,所有可能的取值見 1.2 小節
    • 這個引數是可選的,預設情況下,是以只讀模式 r 開啟檔案
  • open 返回一個 file 物件,通過呼叫 file 物件的成員方法訪問該檔案

使用 open 開啟一個檔案並訪問:

file = open('test.txt')
line = file.readline()
print
(line)
  • 在第 1 行,以只讀方式開啟檔案 test.txt,open 返回一個 file 物件
  • 在第 2 行,呼叫 file 物件的 readline() 方法從檔案中讀取一行

1.2 檔案的訪問模式

下表列出了常用的檔案訪問模式:

模式 描述 如果檔案存在 如果檔案不存在
r 以只讀方式開啟檔案 保留原有內容,從檔案頭部開始讀 丟擲異常 FileNotFoundError
r+ 以讀寫方式開啟檔案 保留原有內容,從檔案頭部開始讀 丟擲異常 FileNotFoundError
w 以只寫方式開啟檔案 刪除原有內容,從檔案頭部開始寫入 建立新檔案
w+ 以讀寫方式開啟檔案 刪除原有內容,從檔案頭部開始讀寫 建立新檔案
a 以只寫方式開啟檔案 保留原有內容,從檔案尾部開始讀寫 建立新檔案
a+ 以讀寫方式開啟檔案 保留原有內容,從檔案尾部開始讀寫 建立新檔案

1.3 關閉檔案

訪問檔案的步驟如下:

  1. 開啟檔案
  2. 讀寫檔案
  3. 關閉檔案

當檔案訪問完畢後,不再需要訪問該檔案時,需要及時的呼叫 file 物件的 close() 方法關閉檔案。以下是及時關閉檔案的例子:

file = open('test.txt')
file.read()
file.close()

2. 檔案物件

open 返回一個 file 物件,通過呼叫 file 物件的成員方法訪問該檔案,下表總結了 file 物件的成員方法。

成員方法 功能
close() 關閉檔案,關閉之後便不能再進行寫入
write(string) 將字串 string 寫入檔案
read(count) 從檔案中讀取一個字串,至多讀取 count 個字元
tell() 獲取檔案的當前訪問位置
seek(offset, from) 改變檔案的當前訪問位置

seek(offset, from) 的功能是根據引數 offset 和 from 改變當前檔案的訪問位置:

  • 引數 offset 表示要移動的位元組數
  • 引數 from 指定開始移動位元組的參考位置
    • 如果 from 被設為 0,將檔案的開頭作為移動的參考位置
    • 如果 from 被設為 1,將檔案的當前訪問位置作為移動的參考位置
    • 如果 from 被設為 2,將檔案的末尾作為移動的參考位置

3. 應用場景

3.1 使用 while 迴圈列印檔案的每行

假設檔案 test.txt 的內容:

www
imooc
com

下面使用 readline() 方讀取檔案的每行並列印:

file = open('test.txt')
while True:
    line = file.readline()
    if line == '':
        break
    print(line, end = '')
file.close()
  • 在第 1 行,以只讀方式開啟檔案 test.txt
  • 在第 3 行,呼叫 readline() 方法讀取檔案的一行,讀取的資料包括換行
  • 在第 4 行,如果讀取到檔案尾部,則返回一個空字串,此時退出迴圈
  • 在第 6 行,預設情況下 print 輸出時會自動加上換行,因為 readline() 返回的資料會包含換行,因此使用命名引數 end = ‘’ 使 print 輸出時不換行

執行程式,程式輸出如下:

www
imooc
com

3.2 使用 for 迴圈列印檔案的每行

Python 中的 file 物件是一個可迭代物件 Iterable,可以使用 for 迴圈遍歷 file 物件。for 迴圈遍歷檔案的每一行,示例如下:

file = open('test.txt')
for line in file:
    print(line, end = '')
file.close()
  • 在第 2 行,使用 for 迴圈遍歷檔案 file 的每一行
    • line 指向當前遍歷的行,包括換行符
  • 在第 4 行, 因為 line 包含換行符,因此使用命名引數 end = ‘’ 使 print 輸出時不換行

3.3 複製檔案

下面的例子實現複製檔案的功能:

def copy(src_path, dst_path):
    src_file = open(src_path, 'r')
    dst_file = open(dst_path, 'w')
    for line in src_file:
        dst_file.write(line)
    src_file.close()
    dst_file.close()

copy('test.txt', 'test.bak')
  • 在第 2 行,以只讀方式開啟原始檔 src_path
  • 在第 3 行,以只寫方式開啟目標檔案 dst_path
  • 在第 4 行,遍歷原始檔 src_file 的每一行 line
  • 在第 5 行,將 line 寫入到目標檔案 dst_file
  • 在第 6 行,及時關閉 src_file 和 dst_file

3.4 向檔案追加內容

編寫一個用於記錄日誌的函式 log(msg),該函式將 msg 寫入到日誌檔案 log.txt 中。每次寫日誌檔案時,需要:

  • 保留日誌檔案的原有內容
  • 將新的記錄新增到日誌檔案的尾部

檔案 log.py 的內容如下:

from datetime import datetime

def log(msg):
    dt = datetime.today()
    now = dt.strftime("%Y-%m-%d %H:%M:%S")
    line = '%s: %s\n' % (now, msg)
    log_file.write(line)

log_file = open('log.txt', 'a')
log('hello')
log('world')
log_file.close()
  • 在第 3 行,編寫函式 log(msg),用於將 msg 追加到日誌檔案 log.txt
    • 在第 4 行到第 5 行,獲取當前時間 now
    • 在第 6 行,將當前時間 now 和資訊 msg 追加到日誌檔案
  • 在第 9 行,以追加模式 a 開啟檔案 log.txt
    • 向檔案寫資料時,資料會被追加到檔案尾部
  • 在第 10 行,向日志中寫入 hello
  • 在第 11 行,向日志中寫入 world
  • 在第 12 行,關閉日誌檔案

執行 log.py,命令如下:

C:\> python log.py
C:\> dir
2020/06/04  11:47    <DIR>          .
2020/06/04  11:47    <DIR>          ..
2020/06/04  11:49               249 log.py
2020/06/04  11:50                56 log.txt
  • 在第 6 行,顯示當前目錄下存在檔案 log.txt
    • 以追加模式 a 開啟檔案 log.txt,如果檔案不存在則建立檔案

此時檔案 log.txt 的內容如下,檔案中包含有兩行文字:

2020-06-04 11:49:54: hello
2020-06-04 11:49:54: world

再次執行程式 log.py,命令如下:

C:\> python log.py

此時檔案 log.txt 的內容如下,檔案中包含有四行文字:

2020-06-04 11:49:54: hello
2020-06-04 11:49:54: world
2020-06-04 11:50:06: hello
2020-06-04 11:50:06: world
  • 第 1 行和第 2 行,是第一次執行 log.py 產生的記錄
  • 第 3 行和第 4 行,是第二次執行 log.py 產生的記錄