寫程式的時候,你一定用過 print() 來看程式跑到哪、變數長怎樣。但如果你的程式已經給別人在用、或是放到伺服器上跑好幾天,出事的時候你人不在電腦前面,print() 印出來的東西早就消失在畫面裡了——這時候就需要 logging。
先用一個比喻:logging 就是程式在寫日記
想像你養了一隻寵物,但你沒辦法一直盯著牠看。於是你在牠的籠子裡裝了一台攝影機,它會自動把每天發生的事情寫成一篇日記:
- 早上 8:00 - 吃飼料了
- 早上 10:00 - 睡著了
- 下午 3:00 - 好像生病了,一直在角落不動
- 下午 3:05 - 沒有反應了,要注意!
你不需要一直守在旁邊看,晚上回家翻一下日記,就知道今天發生了什麼事、什麼時候開始不對勁。
程式的 logging 做的就是同一件事:讓程式在執行的過程中,自己把「發生了什麼事」寫下來,存成一個檔案。之後程式出問題了,你不用重跑一次、也不用在旁邊盯著看,直接打開這份「日記」(在程式的世界裡叫 log 檔),就能知道問題出在哪一步。
那為什麼不要一直用 print 就好?
print() 也是把訊息印出來,乍看之下跟寫日記很像,但差在幾個地方:
print() | logging | |
|---|---|---|
| 訊息會不會消失 | 程式關掉、視窗一關就沒了 | 可以存成檔案,永久留著 |
| 能不能分輕重緩急 | 不行,每一行都長得一樣 | 可以分等級(等一下會講) |
| 能不能一鍵關掉 | 要手動把 print() 刪掉或註解掉 | 改一個設定就能全部關掉或打開 |
| 適合誰用 | 自己寫程式時偷看一下 | 程式正式上線、給別人用的時候 |
簡單說:print() 像是你自己在草稿紙上隨手寫筆記,寫完就丟;logging 才是真正裝了攝影機、認真記錄下來的日記本。
logging 的「等級」:訊息有多嚴重,分開講
日記如果每一句話看起來都一樣重要,那也沒什麼用——「吃飼料了」跟「沒有反應了」明明嚴重程度差很多。所以 logging 把訊息分成幾個等級,從不嚴重到很嚴重:
| 等級 | 白話翻譯 | 什麼時候用 |
|---|---|---|
| DEBUG | 碎碎念 | 只有你自己在除錯的時候想看的細節,例如「現在這個變數是 5」 |
| INFO | 正常播報 | 程式正常運作時的重要事件,例如「使用者登入成功」 |
| WARNING | 有點怪怪的 | 還沒出事,但感覺快出事了,例如「這個檔案快要滿了」 |
| ERROR | 出事了 | 某個功能失敗了,但程式整體還活著,例如「存檔失敗」 |
| CRITICAL | 大事不妙 | 整個程式快要掛掉了,例如「資料庫完全連不上」 |
你可以想成音量大小:DEBUG 是小聲碎念,CRITICAL 是拿大聲公在喊。平常正式上線的時候,你通常只想聽到 WARNING 以上的聲音,不想被一堆 DEBUG 的碎念吵到——這也是 logging 比 print() 厲害的地方:你可以設定「只顯示 WARNING 以上」,那些等級不夠的訊息就會自動被過濾掉,不用整段刪掉程式碼。
實際上 Python 怎麼寫
Python 內建就有 logging,不用額外安裝:
import logging
logging.basicConfig(level=logging.INFO)
logging.debug("這是碎碎念,預設不會顯示")
logging.info("使用者登入成功")
logging.warning("硬碟空間快滿了")
logging.error("存檔失敗")
logging.critical("資料庫連不上了")
執行之後畫面會長這樣:
INFO:root:使用者登入成功
WARNING:root:硬碟空間快滿了
ERROR:root:存檔失敗
CRITICAL:root:資料庫連不上了
注意 logging.debug(...) 那一行沒有出現——因為我們在 basicConfig 設定了 level=logging.INFO,意思是「只播報 INFO 以上的等級」,比 INFO 更小聲的 DEBUG 就被自動過濾掉了。如果哪天想除錯,只要把 level 改成 logging.DEBUG,所有碎念也會一起冒出來,完全不用去改動下面那幾行 logging.xxx(...)。
把日記存成檔案
前面的範例只是印在畫面上,跟 print() 差別還不大。真正的威力在於存成檔案,這樣就算程式關掉了,日記還在:
import logging
logging.basicConfig(
filename="app.log", # 存到這個檔案
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
)
logging.info("程式啟動了")
logging.warning("記憶體用量有點高")
跑完之後,打開 app.log 會看到:
2026-09-17 10:00:01 [INFO] 程式啟動了
2026-09-17 10:00:05 [WARNING] 記憶體用量有點高
有時間、有等級、有訊息——這就是一份完整的「程式日記」。之後不管程式是三天前、三個月前跑的,只要 log 檔還在,你都能回頭翻出來看當時發生了什麼事。
一句話總結
print() 是你自己偷瞄一眼用的草稿紙,寫完就丟;logging 是幫程式裝一台會自動記錄的攝影機,把事情依照嚴重程度分類存下來,不管你人在不在電腦前面,事後都能翻開這份日記,一步一步查出問題到底出在哪。