[Python]解決logging.basicConfig() 無效

更新 發佈閱讀 8 分鐘

當你在開發 Python 應用時,常會使用 logging 模組來記錄程式運行的資訊。不過,你可能會遇到這個令人困惑的問題:

logging 模組一開始就已經「有 handler」時,你後續設定的 basicConfig() 完全無效!

這篇文章將完整解析這個問題的根本原因、如何重現、以及該如何正確解決。


🔍 問題描述:logging.basicConfig() 無效

在 Python 中,最常見的 logging 初始化寫法如下:

import logging

logging.basicConfig(level=logging.DEBUG, format='%(levelname)s: %(message)s')
logging.debug("This is a debug message.")

但當你在某些專案、Jupyter Notebook、或大型框架中執行時,發現 debug()info() 等訊息完全沒出現!

這時候你可能會懷疑是不是格式錯、等級錯,其實——問題很可能是:

logging.hasHandlers() == True

⚠️ 為什麼 basicConfig 會失效?

根據官方文件,logging.basicConfig() 只會在尚未設定任何 handler 時才會生效。如果在你呼叫 basicConfig() 之前,logging 模組的 root logger 已經有 handler,則該設定會被忽略。

你可以透過以下程式碼確認:

import logging

print(logging.getLogger().hasHandlers()) # 如果是 True,表示已經有 handler 存在

在 Jupyter Notebook、某些框架(如 Flask、Django)、或第三方函式庫中,logging 可能早在你自己設定前就被初始化了!


✅ 解決方法一:強制移除所有 handler 再設定

若你能掌控主程式流程,這是最直接、有效的方式:

import logging

# 先移除 root logger 的所有 handlers
root_logger = logging.getLogger()
if root_logger.hasHandlers():
root_logger.handlers.clear()

# 然後再設定 basicConfig
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

logging.debug("重新設定 logging 成功!")

📌 handlers.clear() 是從 Python 3.3 開始支援的。若使用較舊版本,請改用以下方式:

for handler in root_logger.handlers[:]:
root_logger.removeHandler(handler)

✅ 解決方法二:手動添加 handler(繞過 basicConfig)

如果你希望更細緻地控制 logging,也可以不使用 basicConfig,自己建立 handler 並加入 logger:

import logging

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# 建立 StreamHandler 並設定格式
console_handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)

# 若已有 handler,先清除
logger.handlers.clear()
logger.addHandler(console_handler)

logger.debug("手動添加 handler 成功!")

這種方法特別適用於你需要同時輸出到檔案和 console、或設定多個 logger 的情境。


✅ 解決方法三:子 logger 不繼承 handler

如果你使用的是子 logger,例如 logging.getLogger('my.module'),你可以控制它是否繼承 root handler:

logger = logging.getLogger("my.module")
logger.propagate = False # 不要繼承 root handler

# 自訂 handler
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

logger.setLevel(logging.INFO)
logger.info("使用子 logger 且避免繼承 root handler")

🧪 範例重現問題

以下是一個會讓 basicConfig 無效的情境:

import logging

# 第三方模組或其他地方已加入 handler
logging.getLogger().addHandler(logging.NullHandler())

# 接下來 basicConfig 就沒有效果
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s: %(message)s')

logging.debug("這行不會顯示!")

執行後,這行 debug() 不會有輸出。


🔚 結語與建議

當你發現 logging.basicConfig() 沒有效果時,不要懷疑人生——先檢查:

import logging
print(logging.getLogger().hasHandlers()) # 若是 True,代表你要手動清 handler!

✅ 建議實務作法:

  1. 確保 basicConfig() 是程式一開始就設定。
  2. 若不能保證,請先 clear() 所有 handler 再重新設定。
  3. 更進階的控制請用 StreamHandlerFileHandler 自行加入 handler。
  4. 使用多個 logger 時,善用 propagate 控制是否傳遞至 root logger。

如果你需要一個可複用的初始化函式,可以這樣寫:

def setup_logger(level=logging.DEBUG):
logger = logging.getLogger()
if logger.hasHandlers():
logger.handlers.clear()
logging.basicConfig(level=level, format='%(asctime)s - %(levelname)s - %(message)s')

之後只要呼叫:

setup_logger()

就能確保 logging 行為一致、輸出正常。

留言
avatar-img
螃蟹_crab的沙龍
159會員
314內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。 興趣是攝影,踏青,探索未知領域。 人生就是不斷的挑戰及自我認清,希望老了躺在床上不會後悔自己什麼都沒做。
螃蟹_crab的沙龍的其他內容
2025/05/27
隨著 Apple 設備越來越普及,許多人在傳輸或下載 iPhone 照片時,會發現照片的副檔名變成了 .HEIC。這種檔案在 Windows 系統上常常無法直接開啟或編輯,因此了解如何將 .HEIC 圖片轉換成更通用的 .PNG 格式就變得非常重要。 本文將帶你一步步了解 HEIC 是什麼,並使用
Thumbnail
2025/05/27
隨著 Apple 設備越來越普及,許多人在傳輸或下載 iPhone 照片時,會發現照片的副檔名變成了 .HEIC。這種檔案在 Windows 系統上常常無法直接開啟或編輯,因此了解如何將 .HEIC 圖片轉換成更通用的 .PNG 格式就變得非常重要。 本文將帶你一步步了解 HEIC 是什麼,並使用
Thumbnail
2025/04/15
在軟體開發或部署過程中,我們經常需要對多個 .ini 設定檔進行批次修改,例如將某個舊的參數名稱或路徑名稱,替換成新的命名。 這就像記事本的「全部取代」功能,但你不需要一個個打開檔案慢慢點——你可以用 Python 自動完成這些事! 本文將介紹一個 Python 函式:search_and_re
2025/04/15
在軟體開發或部署過程中,我們經常需要對多個 .ini 設定檔進行批次修改,例如將某個舊的參數名稱或路徑名稱,替換成新的命名。 這就像記事本的「全部取代」功能,但你不需要一個個打開檔案慢慢點——你可以用 Python 自動完成這些事! 本文將介紹一個 Python 函式:search_and_re
2025/04/11
🐶 什麼是 Watchdog? Watchdog 是一個 Python 套件,用來即時監控檔案系統的變化。它可以在資料夾內有「新增」、「修改」、「刪除」等事件時,立即觸發事件處理函式,不需要手動輪詢 (polling),效率高又省資源。 ✅ Watchdog 的特點: 採用 OS 層級的檔案
2025/04/11
🐶 什麼是 Watchdog? Watchdog 是一個 Python 套件,用來即時監控檔案系統的變化。它可以在資料夾內有「新增」、「修改」、「刪除」等事件時,立即觸發事件處理函式,不需要手動輪詢 (polling),效率高又省資源。 ✅ Watchdog 的特點: 採用 OS 層級的檔案
看更多
你可能也想看
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
呈上篇,若是在大型系統中使用,重複被調用時,在每次紀錄時都會創建一個新的 FileHandler,這會導致日誌處理器不斷累積,從而使日誌重複記錄。 [Python]使用logging創建兩個以上的日誌紀錄 使用__new__的方法來避免重複調用 改良後 setup_logger 方法中創建一
Thumbnail
呈上篇,若是在大型系統中使用,重複被調用時,在每次紀錄時都會創建一個新的 FileHandler,這會導致日誌處理器不斷累積,從而使日誌重複記錄。 [Python]使用logging創建兩個以上的日誌紀錄 使用__new__的方法來避免重複調用 改良後 setup_logger 方法中創建一
Thumbnail
介紹工作後幾個常見的小問題,包括寫 Log 的好習慣、本地印出錯誤或過程、PHPCS 工具、變數儲存於設定檔、避免魔術數字、程式碼靜態分析與動態分析。
Thumbnail
介紹工作後幾個常見的小問題,包括寫 Log 的好習慣、本地印出錯誤或過程、PHPCS 工具、變數儲存於設定檔、避免魔術數字、程式碼靜態分析與動態分析。
Thumbnail
瞭解如何在Xcode15及以上使用Logger進行更好的程式debug。Logger可以更好的組織Log,但也有一些缺點需要注意。本文將介紹Logger的基本使用方式,以及一些注意事項。
Thumbnail
瞭解如何在Xcode15及以上使用Logger進行更好的程式debug。Logger可以更好的組織Log,但也有一些缺點需要注意。本文將介紹Logger的基本使用方式,以及一些注意事項。
Thumbnail
呈上次使用logging來撰寫日誌,利用類別包裝的方式,可實現多個日誌紀錄器,但發現這樣就失去它原先,可以回傳是誰呼叫他並記錄行數的功能。 [Python]使用logging創建兩個以上的日誌紀錄 若開啟函式名稱、行數及訊息的功能,就會像這樣,幾乎都是記錄到,我定義中類別的函式
Thumbnail
呈上次使用logging來撰寫日誌,利用類別包裝的方式,可實現多個日誌紀錄器,但發現這樣就失去它原先,可以回傳是誰呼叫他並記錄行數的功能。 [Python]使用logging創建兩個以上的日誌紀錄 若開啟函式名稱、行數及訊息的功能,就會像這樣,幾乎都是記錄到,我定義中類別的函式
Thumbnail
logging 是 Python 中用於記錄程式運行時信息的模組,它可以幫助你在開發過程中更好地管理和追蹤程式的執行狀態和錯誤信息。 本文較著重使用兩種不同的方法來創建日誌紀錄。 其他有關logging的教學,我推薦以下文章,他介紹蠻詳細的,我就不多贅述了。
Thumbnail
logging 是 Python 中用於記錄程式運行時信息的模組,它可以幫助你在開發過程中更好地管理和追蹤程式的執行狀態和錯誤信息。 本文較著重使用兩種不同的方法來創建日誌紀錄。 其他有關logging的教學,我推薦以下文章,他介紹蠻詳細的,我就不多贅述了。
Thumbnail
在實務上,若Python報錯時,若引入的套件越多伴隨的異常訊息會變得越來越複雜,看到一推密密麻麻的內容時,很多時候都想直接跳過。 本文將利用Traceback來讓異常訊息變得更好理解。
Thumbnail
在實務上,若Python報錯時,若引入的套件越多伴隨的異常訊息會變得越來越複雜,看到一推密密麻麻的內容時,很多時候都想直接跳過。 本文將利用Traceback來讓異常訊息變得更好理解。
Thumbnail
讀取ini配置文件時如果某個參數不存在,它就會報錯,要怎麼避免呢? 可以使用fallback 參數來指定預設值。 這樣即使配置文件中缺少一些參數,我們的程序也能正常運行並使用預設值。 讓我們來假設一個案例做說明: 先故意將先前範例的port的資料刪掉。
Thumbnail
讀取ini配置文件時如果某個參數不存在,它就會報錯,要怎麼避免呢? 可以使用fallback 參數來指定預設值。 這樣即使配置文件中缺少一些參數,我們的程序也能正常運行並使用預設值。 讓我們來假設一個案例做說明: 先故意將先前範例的port的資料刪掉。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
這個問題發生在我們開發Python的Websocket Server時, 使用以下的程式碼架設服務 start_server = websockets.serve(server, 'localhost', args.port) async with start_server:
Thumbnail
這個問題發生在我們開發Python的Websocket Server時, 使用以下的程式碼架設服務 start_server = websockets.serve(server, 'localhost', args.port) async with start_server:
Thumbnail
IDE 升級後出現了一樣的錯誤,手上程式碼沒有 pylint black-format 檢查上不了 gitlab,我又點開了那個很小很小的 x 符號,裡面 logs 提示的解決方式是升級..
Thumbnail
IDE 升級後出現了一樣的錯誤,手上程式碼沒有 pylint black-format 檢查上不了 gitlab,我又點開了那個很小很小的 x 符號,裡面 logs 提示的解決方式是升級..
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News