You are currently viewing Python Logging 教學:為什麼你該戒掉 print()

Python Logging 教學:為什麼你該戒掉 print()

很多剛開始寫 Python 的人,習慣用 print() 來查看程式運作狀況。但在專案規模變大時,你很快就會遇到瓶頸:

  • 訊息大爆炸:重要錯誤與無關緊要的除錯訊息混在一起,難以閱讀。
  • 無法存檔:想要追蹤過去發生的錯誤,卻發現終端機關掉就沒了,只能自己寫程式存檔。
  • 來源不明:當有很多檔案時,很難分辨這行訊息到底是從哪個模組印出來的。

這時候,Python 內建的 logging 模組就是你的救星。它能幫你分級管理訊息、自動存檔,並讓除錯變得專業又輕鬆。


1. 快速上手:基本使用方式

使用 logging 非常簡單,只需三個步驟:匯入、設定、輸出。

import logging

# 1. 設定基本配置 (預設等級設為 INFO)
logging.basicConfig(level=logging.INFO)

# 2. 建立 logger (建議使用 __name__ 讓 log 知道是哪個檔案發出的)
logger = logging.getLogger(__name__)

# 3. 輸出不同等級的訊息
logger.debug("這是 debug 訊息(開發除錯用)")
logger.info("這是 info 訊息(一般資訊)")
logger.warning("這是 warning 訊息(警告)")
logger.error("這是 error 訊息(錯誤)")
logger.critical("這是 critical 訊息(嚴重崩潰)")

2. 搞懂「日誌等級 (Log Levels)」

logging 的核心在於「等級」。你可以決定現在只想看「錯誤」,還是想看「所有細節」。

由低到高(嚴重程度)共有五種等級:

等級說明適用情境
DEBUG最詳細的訊息開發時用來追蹤變數、迴圈狀態,除錯用。
INFO一般資訊確認程式正如預期執行中(例如:連線成功、任務開始)。
WARNING警告訊息程式沒掛掉,但有潛在問題(例如:磁碟空間不足、使用了過期函式)。
ERROR錯誤訊息程式某個功能執行失敗,但整體還能跑(例如:存檔失敗)。
CRITICAL致命錯誤程式嚴重崩潰,可能無法繼續執行。

注意:如果你設定 level=logging.INFO,那麼比 INFO 低階的 DEBUG 訊息就會被自動過濾掉(不顯示)。

3. 讓訊息更清楚:格式化 (Formatting)

預設的輸出有點單調,我們可以加上時間嚴重等級訊息內容,讓 Log 一目了然。

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

logger.info("格式化後的輸出看起來專業多了")

輸出範例:

2023-10-27 10:30:01,123 - INFO - 格式化後的輸出看起來專業多了

4. 將 Log 存入檔案

在正式環境(Production)中,我們通常沒辦法一直盯著螢幕看,這時需要把 Log 寫入檔案。

logging.basicConfig(
    filename="app.log",      # 指定檔案名稱
    filemode="a",            # 'a' 代表 append (附加模式),'w' 代表每次重寫
    level=logging.DEBUG,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

這樣設定後,所有的訊息都會自動被寫入 app.log,方便日後查閱。


5. 進階技巧:用環境變數控制 Debug 模式

在開發時我們想看 DEBUG 訊息,但在正式上線時只想看 INFOWARNING。頻繁改程式碼很麻煩,不如用「環境變數」來控制。

程式碼寫法:

import logging
import os

# 從環境變數讀取 LOG_LEVEL,沒有設定則預設為 'INFO'
log_level = os.getenv("LOG_LEVEL", "INFO").upper()

logging.basicConfig(
    # 將字串轉換為 logging 的常數 (例如 "DEBUG" -> logging.DEBUG)
    level=getattr(logging, log_level, logging.INFO),
    format="%(asctime)s - %(levelname)s - %(message)s"
)

logger = logging.getLogger(__name__)

logger.debug("這行只有在 DEBUG 模式才看得到")
logger.info("這行在 INFO 模式看得到")

執行方式:

  • 一般執行(預設 INFO)
    bash python app.py
  • 開啟除錯模式
    bash LOG_LEVEL=DEBUG python app.py

6. 在多檔案專案中的最佳寫法

當你的專案有多個 .py 檔案時,不要在每個檔案都呼叫 basicConfig(這只要在主程式進入點設定一次就好)。

在其他模組(Module)中,你只需要這樣做:

# utils.py 或其他模組檔案
import logging

# __name__ 會自動帶入模組名稱 (例如 utils)
logger = logging.getLogger(__name__)

def do_something():
    logger.info("正在執行某個功能...")

這樣做的好處是,Log 輸出時會顯示 utils,讓你一眼就知道這行訊息是從哪個檔案發出來的,追蹤問題超方便。


7. 總結與最佳實踐

  1. 小專案用 print,大專案一定要用 logging
  2. 善用等級過濾
    • 開發環境(Development):設定為 DEBUGINFO
    • 正式環境(Production):建議設定為 WARNINGERROR,避免 Log 檔過大塞爆硬碟。
  3. 使用 __name__:建立 Logger 時務必使用 logging.getLogger(__name__) 以利追蹤來源。
  4. 進階學習:如果專案更大,建議研究 Handlers(同時輸出到螢幕和檔案)與 RotatingFileHandler(Log 檔太大時自動切割)的功能。
0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments