関数内にログをベタベタ書くと見づらいのでデコレータで
外に吐き出しました。(結果的に一層長くなりましたが...)
もっと短く書けないか考え中です。
以下、足し算・引き算の例です。
import logging
import sys
import functools
class CalculatorLogger:
def __init__(self, logger_name):
self.logger = logging.getLogger(logger_name)
self.logger.setLevel(logging.INFO)
# ログが重複しないように、既存のハンドラーがあれば削除
if self.logger.hasHandlers():
self.logger.handlers.clear()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s')
# ログをコンソールに出力するハンドラーを追加
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler)
class Calculator:
def __init__(self):
self._result = 0
self.logger = CalculatorLogger(__name__)
# デコレーター: 関数の説明をログに含める
def log_description(description):
def decorator(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
self.logger.logger.info(f'{func.__name__}: {description} 関数が呼び出されました。')
result = func(self, *args, **kwargs)
self.logger.logger.info(f'{func.__name__}: {description} 関数の実行が終了しました。')
return result
return wrapper
return decorator
# デコレーター: プロパティ変数の更新前後の値をログに残す
def log_property_change(prop):
def decorator(func):
@functools.wraps(func)
def wrapper(self, value):
old_value = getattr(self, prop)
func(self, value)
new_value = getattr(self, prop)
if old_value != new_value: # 更新がある場合のみログ出力
self.logger.logger.info(f'{func.__name__}: {prop} 変数が更新されました。変更前: {old_value}, 変更後: {new_value}')
setattr(self, prop, new_value) # プロパティの値を更新
return wrapper
return decorator
# 整数チェック
def is_integer(value):
try:
int(value)
return True
except ValueError:
return False
# 足し算
@log_description('足し算')
@log_property_change('_result')
def add(self, value):
if not Calculator.is_integer(value):
self.logger.logger.error('整数以外の値が指定されました。')
sys.exit(1)
self._result += int(value)
# 引き算
@log_description('引き算')
@log_property_change('_result')
def subtract(self, value):
if not Calculator.is_integer(value):
self.logger.logger.error('整数以外の値が指定されました。')
sys.exit(1)
self._result -= int(value)
# プロパティ変数のゲッター
@property
def result(self):
return self._result
# クラスのインスタンス化
calc = Calculator()
# 足し算と引き算のログ出力付き操作
calc.add(5)
calc.subtract(2)
# プロパティ変数のログ出力
print(calc.result) # 現在の計算結果を表示
# エラーチェック:整数以外の引数
calc.add("abc")