
logging 【日誌】
Logging
Logging library module 允許開發人員將日誌功能整合到他們的應用程序中,從而在運行時記錄事件、錯誤和其他重要信息。

print()
是沒有嚴重性概念的普通文本。而 Logging 具有 4 個級別的日誌訊息嚴重性或重要性,有助於從訊息忽略較低嚴重性的訊息。
info(msg, *args, **kwargs)
監視和理解應用程序行為。(例如: 報告流程、事件、顯示狀態)
debug(msg, *args, **kwargs)
用於開發和測試階段。(例如: 記錄變數值、路徑、內部狀態)
warning(msg, *args, **kwargs)
表示問題已經發生或即將發生,但應用程序仍可以繼續運行。
error(msg, *args, **kwargs)
表示特定操作或任務失敗或遇到異常。錯誤通常會阻止應用程序按預期運行或產生不正確的結果。
critical(msg, *args, **kwargs)
表示對應用程序的功能有重大的嚴重錯誤。當此類事件發生時,應用程序可能處於不穩定或不可恢復的狀態。
import logging
# log
logging.info("[This is a info]")
logging.warning("[This is a warning]")
logging.error("[This is a error]")
logging.critical("[This is a critical]")
執行結果
WARNING:root:[This is a warning]
ERROR:root:[This is a error]
CRITICAL:root:[This is a critical]
最佳的紀錄工具
顯示在 Terminal
print()
監控或故障調查
logging.info()
、 logging.debug()
發出事件的警告
logging.warning()
(注意該事件)、warnings.warn()
;(必須修正該事件)
報告事件的錯誤
引發 Exception。詳見: [[exception 【異常】]]
抑制錯誤而不引發異常 (例如: 伺服器中的 Threading)
logging.error()
, logging.exception()
, logging.critical()
basicConfig
快速設定多個屬性 (logger、FileHandler...)
logging.basicConfig(**kwargs)
常用的參數:
filename
寫入日誌訊息的檔案名稱,否則輸出在 Terminal。
filemode
寫入模式,即 open()
。如果指定 filename
,則使用 "a"
。
format
需要寫入的日誌訊息。詳見: LogRecord attributes。
datefmt
指定的日期/時間格式。與 time.strftime() 的格式相同。
style
日誌訊息的格式('%'
, '{'
, '$'
),預設為%
。
level
設置根記錄器級別,不會記錄較小的級別的日誌。級別大小為: DEBUG
< INFO
< WARNING
< ERROR
< CRITICAL
。
encoding
編碼模式。常使用 encoding="UTF-8"
。
fileConfig
fileConfig()
允許使用 Configuration file 設定日誌記錄,而不是透過程式碼的方式定義。 支持的格式有:.ini、.yaml、.json。
透過使用 logging.config.fileConfig()
,您可以將日誌記錄設定與您的程式碼分開,從而在不修改代碼本身的情況下更輕鬆地管理。此外,您可以為不同的環境或模塊使用不同的 Configuration file。
logging.config.fileConfig(fname,
defaults=None,
disable_existing_loggers=True,
encoding=None)
Logger
建立 Logger ,可以過濾 log 資訊。
設定 Logger。
logging.getLogger(name=None)
logging.getLogger(loggeyr_1) # Ex1.
logging.getLogger(logger_1.logger_1_2) # Ex2. 可以使用`.` 代表 Logger 的階層。
建議使用 logger.getLogger(__name__)。
因為它將返回當前的 package 命名空間。如果有多個.py 檔案時很有用。
Handler
如何處理 Logger 的資訊。
將 Logger 輸出到 File。
logging.FileHandler(filename,
mode='a',
encoding=NoHne,
delay=False,
errors=None)
將 Logger 輸出到 Terminal。
logging.StreamHandler(stream=None)
將 Logger 輸出到 Web 。
handlers.HTTPHandler(host,
url,
method='GET',
secure=False,
credentials=None,
context=None)
設定 Handler 屬性。 其他屬性詳見:logging.Handler
file_handler = logging.FileHandler('app.log')
# =========================================================
# level
file_handler.setLevel(logging.INFO)
# Formatter
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
Filter
Filter class 允許您自定義過濾器以根據特定條件有選擇地過濾掉日誌記錄。 它提供了一種微調日誌記錄系統中日誌記錄處理的方法。
Filter Filter class 是一個 base class, 它提供了一個 filter(record)
的方法,您需要在子 class 中覆蓋該方法。 filter()
方法將日誌記錄作為輸入,如果返回 True,則處理該日誌;則返回 True,如果返回 False,則跳過該日誌 。
過濾器與日誌級別將會一起運行,日誌級別具有較高的優先度。
例如:如果日誌級別設置為 WARNING,則只有 WARNING 或更高級別的日誌記錄才會被處理,而不管過濾器的設定。
範例
basicConfig
'''basicConfig'''
import logging
# 建立 logger 和 FileHandler
logging.basicConfig(filename = 'log.txt',
level = logging.DEBUG,
format = '{asctime}: {levelname}: {name}: {message}',
style='{')
#format = '%(asctime)s:%(levelname)s:%(name)s:%(message)s')
logging.debug('Debug message')
logging.info('Info message')
logging.warning('Warning message')
logging.error('Error message')
logging.critical('Critical message')
執行結果:

'''
basicConfig ->logger
->logger
'''
import logging
# 設定多個屬性
logging.basicConfig(filename='app.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
# =========================================================
# logger 1
logger = logging.getLogger('my_logger_1')
logger.setLevel(logging.DEBUG)
# log
logger.debug('This is a debug message.') # ✔️✔️
logger.info('This is an informational message.') # ✔️✔️
logger.warning('This is a warning message.') # ✔️✔️
# =========================================================
# logger 2
logger_2 = logging.getLogger('my_logger_2')
logger_2.setLevel(logging.WARNING)
# log
logger_2.debug('This is a debug message.')
logger_2.info('This is an informational message.')
logger_2.warning('This is a warning message.') # ✔️✔️
執行結果:
2023-07-19 18:18:20,495 - DEBUG - This is a debug message.
2023-07-19 18:18:20,495 - INFO - This is an informational message.
2023-07-19 18:18:20,495 - WARNING - This is a warning message.
2023-07-19 18:18:20,495 - WARNING - This is a warning message.
fileConfig
[loggers]
keys=root
[handlers]
keys=fileHandler, consoleHandler
[formatters]
keys=defaultFormatter
[logger_root]
level=DEBUG
handlers=fileHandler, consoleHandler
[handler_fileHandler] # 輸出到 檔案
class=FileHandler
level=DEBUG
formatter=defaultFormatter
args=('example.log', 'a')
[handler_consoleHandler] # 輸出到 Terminal
class=StreamHandler
level=DEBUG
formatter=defaultFormatter
args=(sys.stdout,)
[formatter_defaultFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=%Y-%m-%d %H:%M:%S
version: 1
formatters:
defaultFormatter:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
datefmt: "%Y-%m-%d %H:%M:%S"
handlers:
fileHandler: # 輸出到 檔案
class: logging.FileHandler
level: DEBUG
formatter: defaultFormatter
filename: app.log
consoleHandler: # 輸出到 Terminal
class: logging.StreamHandler
level: DEBUG
formatter: defaultFormatter
stream: ext://sys.stdout
loggers:
root:
level: DEBUG
handlers: [fileHandler, consoleHandler]
propagate: yes
import yaml
import logging
import logging.config
# 載入 configuration_file.conf,建立 logger
logging.config.fileConfig('logging.conf')
logger = logging.getLogger(__name__)
# 寫入 Log
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
# =========================================================
# 載入 configuration_file.yaml,建立 logger
with open('logging.yaml', 'r') as f:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)
logger = logging.getLogger(__name__)
# 寫入 Log
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger
'''getLogger('my_logger') ->FileHandler'''
import logging
# 建立 logger
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)
# 建立 FileHandler
file_handler = logging.FileHandler('app.log')
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
# 加入 handler
logger.addHandler(file_handler)
# 寫入 log
logger.info('This is an informational message.')
logger.warning('This is a warning message.')
執行結果:
2023-07-19 17:58:12,393 - INFO - This is an informational message.
2023-07-19 17:58:12,393 - WARNING - This is a warning message.
'''getLogger(__name__) ->FileHandler'''
import logging
# 建立 logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)s - %(asctime)s - %(levelname)s - %(message)s')
# 建立 FileHandler
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.WARNING)
file_handler.setFormatter(formatter)
# 加入 handler
logger.addHandler(file_handler)
# log
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
執行結果:
__main__ - 2023-07-19 18:01:14,806 - WARNING - This is a warning message
__main__ - 2023-07-19 18:01:14,806 - ERROR - This is an error message
Handler
import logging
# 設定多個屬性
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
# =========================================================
# 建立 FileHandler
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
# =========================================================
# 建立 StreamHandler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
# =========================================================
# 加入 handler
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# =========================================================
# 寫入 log
logger.debug('This is a debug message.')
logger.info('This is an informational message.')
logger.warning('This is a warning message.')
執行結果:
2023-07-19 18:04:38,094 - DEBUG - This is a debug message.
2023-07-19 18:04:38,094 - INFO - This is an informational message.
2023-07-19 18:04:38,094 - WARNING - This is a warning message.
2023-07-19 18:04:38,094 - INFO - This is an informational message.
2023-07-19 18:04:38,094 - WARNING - This is a warning message.
Filter
import logging
class LoggerFilter(logging.Filter):
def filter(self, record):
return record.levelno >= logging.WARNING
class HandlerFilter(logging.Filter):
def filter(self, record):
if record.msg.find('abc') == -1:
return True
return False
# 建立 Handler
logger = logging.getLogger('test')
logger.setLevel(logging.INFO)
# 建立 Handler
stream_handler = logging.StreamHandler()
logger.addHandler(stream_handler)
# =========================================================
logger.warning('this is warning-1') # ✔️✔️
logger.info('this is info-1') # ✔️✔️
# =========================================================
logger.addFilter(LoggerFilter())
logger.warning('this is warning-2') # ✔️✔️
logger.info('this is info-2') # Skip this log
# =========================================================
stream_handler.addFilter(HandlerFilter())
logger.warning('this is warning-3') # ✔️✔️
logger.info('this is info-3') # Skip this log
logger.warning('this is warning-abc') # Skip this log
執行結果:
this is warning-1
this is info-1
this is warning-2
this is warning-3
Logger Decorator
import logging
def logger(func):
def wrapper(*args, **kwargs):
logging.info(f"Running \"{func.__name__}\" with arguments {args} and kwargs {kwargs}")
result = func(*args, **kwargs)
logging.info(f"{func.__name__} returned {result}")
return result
return wrapper
logging.basicConfig(level=logging.INFO)
@logger
def adder(x, y):
return x + y
print(adder(10, 5))
執行結果:
INFO:root:Running "adder" with arguments (10, 5) and kwargs {}
INFO:root:adder returned 15
15
import logging
class LevelFilter(logging.Filter):
"""
This is a custom filter class that filters out log messages below certain level.
"""
def filter(self, record):
return record.levelno >= logging.INFO
def setup_logger():
logger = logging.getLogger('custom_logger')
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# Create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(formatter)
logger.addHandler(ch)
# Create file handler which logs even debug messages
fh = logging.FileHandler('log_file.log')
fh.setLevel(logging.INFO)
fh.setFormatter(formatter)
logger.addHandler(fh)
# Add filter to the logger
logger.addFilter(LevelFilter())
return logger
logger = setup_logger()
def logger_decorator(func):
def wrapper(*args, **kwargs):
logger.info(f"Running \"{func.__name__}\" with arguments {args} and kwargs {kwargs}")
result = func(*args, **kwargs)
logger.info(f"{func.__name__} returned {result}")
return result
return wrapper
@logger_decorator
def adder(x, y):
return x + y
print(adder(10, 5))
執行結果:
2023-07-19 18:40:51,589 - custom_logger - INFO - Running "adder" with arguments (10, 5) and kwargs {}
2023-07-19 18:40:51,589 - custom_logger - INFO - adder returned 15
15
參考資料
Python Doc
基礎 Logging 指南 — Python 3.11.3 說明文件
logging.basicConfig — Python 3.11.3 說明文件
logging.getLogger — Python 3.11.3 說明文件
config.fileConfig — Python 3.11.3 documentation
Blog
Logging in Python - MachineLearningMastery.com
Logging in Python ——真正的 Python
Python 日誌記錄基礎:方法教程、示例及更多 - Sematext
在 Python 中登錄 - MachineLearningMastery.com
如何使用logging.Filter? | Python笔记
Python logging 模組之 logging.basicConfig 用法和參數詳解_Sir靜堂的博客-CSDN博客
Last updated
Was this helpful?