National Taiwan University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

1

Local AI

--

Uedu Code

--

台灣大學 AQI 69 24°C PM2.5 18
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 18

檔案的讀寫

open() 的模式、read/readline/write 與 with
Interaction實作 25 minute(s)

Learning Objectives

  • Python 內建函數 open() 的用法與開檔模式
  • write()、read()、readline() 的用法,以及用 for 逐列讀取
  • with 敘述的應用:自動關閉檔案

為什麼要讀寫檔案

到目前為止,程式的輸入來自 input()(標準輸入,預設是鍵盤),輸出交給 print()(標準輸出,預設是螢幕)。 程式一結束,變數裡的資料就不見了。要把資料保存下來、或讀取別人準備好的資料,就要用檔案。

f = open(檔名, 模式)     # 開啟檔案,得到檔案物件
f.write(...) / f.read()  # 寫入或讀取
f.close()                # 關閉檔案

本課的範例會在工作目錄先放好 note.txt(內容是「中央大學」「ncu」「ncu.edu.tw」三列)。 程式執行後,輸出區的「檔案」分頁會顯示工作目錄裡的檔案內容。

範例統一使用 UTF-8 編碼的文字檔。在自己的電腦上,建議寫成 open('note.txt', 'r', encoding='utf-8'), 不然 Windows 可能用系統預設的編碼(例如 cp950)開啟,中文會變成亂碼。

開檔模式

open() 的第二個引數是模式,預設是 'rt'(讀取文字檔):

模式 說明
'r' 開檔讀資料(預設);檔案不存在會出現 FileNotFoundError
'w' 開檔寫資料,會先清空檔案;檔案不存在就建立
'x' 開檔寫資料,檔案已存在就失敗(FileExistsError)
'a' 開檔寫資料,附加在檔案結尾
'b' 以二進位模式開啟(例如圖片),搭配其他模式寫成 'rb'、'wb'
't' 以文字模式開啟(預設)
'+' 開啟檔案做更新,可以讀也可以寫,例如 'r+'

互動練習:各種模式會做什麼

選一種模式、選檔案原本存不存在、再選要寫入還是讀取,看看檔案內容與檔案指標(下一次讀寫的位置)會變成怎樣。試試看:用 'r' 開啟不存在的檔案、用 'w' 開啟已有內容的檔案,各會發生什麼事?

寫入檔案:w 與 a

write() 把字串寫進檔案,不會自動加換行,要換行就自己寫 '\n'。播完後打開輸出區的「檔案」分頁,看看 note.txt 的內容。把第 10 行的 'a' 改成 'w' 再跑一次,結果有什麼不同?

讀取檔案:read()

read(size) 讀 size 個字元並傳回字串;省略 size 就讀到檔案結尾。讀過的部分不會重讀:第二次 read() 從上一次停下來的地方繼續。

一次讀一列:readline()

readline() 每次讀一列,保留結尾的換行字元;讀到檔案結尾(EOF)時傳回空字串 ''。空字串在 if 裡是 False,所以 if not line: break 可以判斷讀完了。

用 for 逐列讀取,以及 readlines()

檔案物件可以直接放進 for,每一圈拿到一列,這是最常用的寫法。readlines() 則一次把所有列讀成串列。注意每一列結尾的 \n,通常會用 strip() 去掉。

追蹤檔案讀寫

1.

下面的程式會印出什麼?

f = open("t.txt", "w")
f.write("ab")
f.write("cd\n")
f.close()
f = open("t.txt", "a")
f.write("ef")
f.close()
f = open("t.txt")
print(repr(f.read()))
f.close()
2.

下面的程式會印出什麼?

f = open("t.txt", "w")
f.write("one\ntwo\n")
f.close()
f = open("t.txt")
print(repr(f.readline()), repr(f.readline()), repr(f.readline()))
f.close()
3.

note.txt 原本有三列資料。執行 open("note.txt", "w") 之後立刻 close(),note.txt 會變成怎樣?

第 1 次作答

記得關檔:try/finally 與 with

開啟的檔案要 close():寫入的資料可能還在暫存區,沒關檔就不保證寫進去;開太多檔案也會耗盡系統資源。 問題是,讀寫途中發生例外,close() 那一行就執行不到了。傳統作法是把 close() 放進 finally; with 敘述則把「準備」與「清理」包起來,離開區塊時一定會自動關檔,寫法更簡潔:

with open('note.txt', 'r') as fp:
    data = fp.read()
    print(data)
# 離開 with 區塊,fp 已經關閉

沒有 with:try/finally 自己關檔

先把 fp 設成 None,開檔失敗時 finally 才知道不用關。把第 4 行的檔名改成不存在的 nofile.txt 再跑一次,看看流程怎麼走(FileNotFoundError 屬於 OSError)。

with 敘述:自動關檔

with open(...) as fp: 開檔後把檔案物件指派給 fp。注意 fp.closed 在區塊裡是 False,離開區塊後變成 True。最後一段用 with 寫入 log.txt,執行後到「檔案」分頁查看。

想一想:with

1.

下面的程式會印出什麼?

with open("t.txt", "w") as f:
    f.write("hi")
    print(f.closed, end=" ")
print(f.closed)
2.

關於 with open(...) as f:,下面哪一個敘述正確?

第 1 次作答

實作:寫入成績再讀回來加總

程式已經把三個成績寫進 scores.txt(每列一個)。請用 with 開啟 scores.txt,逐列讀取、轉成整數後加總,最後印出 總分 255。

你的輸出
預期輸出

重點精華回顧

  • open(檔名, 模式) 傳回檔案物件;常用模式 'r' 讀、'w' 寫(先清空)、'a' 附加、'x' 新建(已存在就失敗),'b' 二進位、'+' 可讀可寫。
  • write(字串) 不會自動加換行;read(size) 讀 size 個字元,省略就讀到結尾;readline() 讀一列並保留 \n,讀到結尾傳回 ''。
  • 用 for line in 檔案物件: 逐列讀取最常見;readlines() 一次讀成串列。
  • 檔案用完要 close();有例外時用 try/finally 確保關閉。
  • with open(...) as f: 離開區塊時自動關檔,即使中途發生例外,是讀寫檔案的建議寫法。
  • 在自己的電腦上,中文文字檔請加 encoding='utf-8'。
這一課完成了!
Next lesson:標準模組:sys 與 os
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。