loguruを使ってPythonロガーを簡単に扱おう
今回は、Pythonのロガーを簡単に利用できるようにしたloguru
を紹介しようと思います。
※ 本記事ではサンプルコードの生成のために一部claude codeを利用しています。
Pythonでログを取る方法について
まずはPythonでログを取る方法についてそもそもどうやるのかをみていきましょう。
Pythonには標準機能としてlogging
モジュールを使うことが多いと思います。例えば最低限の用意でロガーを用意する場合以下のようにすると作成できます。
import logging
from logging import getLogger
logging.basicConfig(level=logging.INFO)
logger = getLogger(__name__)
logger.debug("This is debug")
logger.info("This is info")
例えばこれを実行すると以下のようになります。
python default_logging.py
# 結果
DEBUG:__main__:This is debug
INFO:__main__:This is info
この結果ですが、標準出力にうまく連携されていないので、例えばpython default_logging.py | pbcopy
のようにしてもクリップボードにはコピーされません。
また、フォーマットの設定をしようとするとFormatterを導入したり、ファイルに出力しようとするとFileHandlerを作成したりと正直かなり厄介になります。
loguruを利用するモチベーション
後ほど実装はお見せしますが、標準のlogging
を利用すると記述量が圧倒的に増えてしまうのに対して、loguru
ではある程度抽象化してくれているので設定がとてもシンプルになります。例えば先ほどの例を書き換えると以下のようになります。
import sys
from loguru import logger
logger.remove()
logger.add(sys.stdout, level="INFO")
logger.add(level="DEBUG")
logger.debug("This is debug")
logger.info("This is info")
この例だけ見ると、「なんだ、量増えてるじゃん」と思われるかもしれませんが、フォーマッターとかを入れたりすると一気に簡単になるので紹介します。
loguru使ってみる
インストール
以下のようにすると環境を構築できます。
uv init loguru_test -p 3.12
cd loguru_test
uv add loguru
ローテーションの実装
まずはログローテーションをする例をみてみましょう。まずは例として1MBごとに新しいファイルにログを残すコードを実装してみます。まずはlogging
を使う例をみてみましょう。なお、最初に言及したようにlogging
を使うのは大変なので、皆さんの友達claude codeを利用しました。
import logging
from logging.handlers import RotatingFileHandler
import os
def setup_rotating_logger():
logger = logging.getLogger('rotating_logger')
logger.setLevel(logging.INFO)
log_dir = 'logs'
if not os.path.exists(log_dir):
os.makedirs(log_dir)
handler = RotatingFileHandler(
filename=os.path.join(log_dir, 'app.log'),
maxBytes=1024*1024, # 1MB
backupCount=5
)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
if __name__ == "__main__":
logger = setup_rotating_logger()
# テスト用のログ出力
for i in range(10000):
logger.info(f"This is log message {i}")
logger.warning(f"This is warning message {i}")
logger.error(f"This is error message {i}")
print("ログファイルが作成されました。logsディレクトリを確認してください。")
容量に応じてログローテーションをするために以下のように実装しています。手順としては以下になりますね。
- ローテーションをするためにファイルハンドラーを作成する
- ハンドラーにログのフォーマッターを設定する
- ファイルハンドラーをロガーに設定する
handler = RotatingFileHandler(
filename=os.path.join(log_dir, 'app.log'),
maxBytes=1024*1024, # 1MB
backupCount=5
)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
こちらを実行すると、logs
フォルダにログが生成され、1MBを超えるとそれまでログを記録していたファイルが末尾に通し番号をつけた上でファイルがローテーションされます(例えばlogs/app.log.1
)。
それではこれと全く同じことをloguru
を使って実装します。実装は以下になります。
import sys
from loguru import logger
import os
def setup_rotating_logger():
logger.remove()
logger.add(sys.stdout, colorize=True, format="{time} - {name}:{line} - {level} - {message}", level="INFO")
logger.add(os.path.join("logs", "app.log"), rotation="1 MB", retention=2)
log_dir = 'logs'
if not os.path.exists(log_dir):
os.makedirs(log_dir)
if __name__ == "__main__":
setup_rotating_logger()
# テスト用のログ出力
for i in range(10000):
logger.info(f"This is log message {i}")
logger.warning(f"This is warning message {i}")
logger.error(f"This is error message {i}")
print("ログファイルが作成されました。logsディレクトリを確認してください。")
どうでしょう?パッとみてもとてもシンプルになっていることがわかるかと思います。loguru
では設定の反映を基本的にlogger.add
で集約させられています。これのおかげでまとめて設定を反映させることができます。出力フォーマットとローテーションの設定を合わせても2行で対応できています。ちなみにフォーマットを設定する前はカラーリングが自動で作成されますが、フォーマットを指定すると色を自分で指定する必要があります。
logger.add(sys.stdout, colorize=True, format="{time} - {name}:{line} - {level} - {message}", level="INFO")
logger.add(os.path.join("logs", "app.log"), rotation="1 MB", retention=2)
まとめ
今回はPythonでロガーをシンプルに扱えるloguruを紹介しました。紹介した機能意外にも色々用意されており、どれもほとんどがlogger.add
の形式で設定でき、とても扱いやすくなっております。直接logging
を利用しなくてもいい感じに実装できるのでぜひ参考にしてください。
Discussion