ロギングとは?
来客履歴や気温、販売記録などのログを記録することです。
Pythonでロギングを行う場合はloguruというモジュールが便利です。
loguru(ログルやログルーと読みます)と言います。
プログラムを書いているとprint()文で動作や表示をチェックすることがあると思います。
でもprint文でロギングを行うことはデメリットがあります。
print文の問題点
1, 重要度が分からなくなる
print文ではどれも同じ重要度に見えます。
2, コメントアウトや削除が面倒
3, コンソール(ターミナル)にしか出ないので不便
このような問題をloguruは解決してくれます。
loguruのメリット
1, 重要度で分けられます
2, 不要なログは表示しないという設定が可能です
3, コメントアウトはいりません
4, ファイルに自動送信してくれます
1の重要度がロギングのレベルです。
ロギングのレベル
Loguruだけではなくてロギングには5つの共通のレベルがあります。
簡単に説明すると以下です。
DEBUG → 開発中に見る
INFO → 普通の情報
WARNING → 注意
ERROR → 失敗
CRITICAL → 大事故
重要度と詳細度 :
DEBUG → INFO → WARNING → ERROR → CRITICAL
(重要度: 低 → 高 )
(詳細度: 高 → 低)
loguruにおけるレベル
上記のロギングのレベルに加えて、TRACEやSUCCESSなどがloguruでは増えています。
| レベル | デフォルト数値 | 説明 | 使いどころ |
|---|---|---|---|
| TRACE | 5 | 非常に詳細な情報 | 関数の入り口・出口、変数の中身などの詳細確認(開発用) |
| DEBUG | 10 | デバッグ用 | 処理フローや変数の値を確認 |
| INFO | 20 | 通常の運用情報 | 正常な処理やイベントの記録 |
| SUCCESS | 25 | 成功を強調 | 特に重要な成功イベント(処理完了、メール送信成功など) |
| WARNING | 30 | 注意が必要な状態 | 軽微な問題や注意喚起 |
| ERROR | 40 | 処理失敗 | 明確なエラーや例外 |
| CRITICAL | 50 | 致命的 | システム全体に影響する重大障害、サービス停止など |
重要度と詳細度 :
TRACE → DEBUG → INFO → SUCCESS → WARNING → ERROR → CRITICAL
(重要度: 低 → 高)
(詳細度: 高 → 低)
デフォルト値とは :
数値が大きいほど重要度が高いです。
実際にはコードでは”DEBUG”などと名前を使うのでデフォルト値はほとんどコード内で使われることはありません。
簡単なログの表示のしかた
まずは簡単に「Hello, Loguru!」とコンソールに表示してみましょう。
基本
logger.<重要度>(“出力したい内容”)
from loguru import logger
logger.info("Hello, Loguru!")
出力
出力の内容の説明
日時 | 重要度 | 今実行しているプログラムの名前: コードがある関数名: 行数 – 入力内容
ロギングレベルごとの表示のやり方
from loguru import logger
# すべてのレベルでログを出力
logger.trace("これは TRACE レベルです")
logger.debug("これは DEBUG レベルです")
logger.info("これは INFO レベルです")
logger.success("これは SUCCESS レベルです")
logger.warning("これは WARNING レベルです")
logger.error("これは ERROR レベルです")
logger.critical("これは CRITICAL レベルです")
出力
print文よりも色が分かれていて分かりやすい表示になっています。
TRACEだけ表示されていませんがこれは LoguruではTRACEは表示されない設定になっているのです。
(TRACEが関数の入り口や変数の中身まで全部表示するような使い方をするからです。そうなるとコンソールが文章で埋まってしまい不便です。)
レベルの使いどころ
重要度の一番低いTRACEを多く使います。
変数の中身や書くプロセス、関数の入り口や詳細情報を知りたいときに使います。
二番目に低いDEBUGも良く使います。
処理の分岐や中間結果を確認したいときです。
INFOは処理の進歩や重要なイベントです。ユーザーがログインするなどアクションが行われた時などに使います。
SUCCESSは処理が成功したことを表示します。
WARNINGは注意すべきことでも処理は継続可能な時に表示
ERRORは処理できなかったエラー、修正が必要です
CRITICALはシステム全体に影響する重大な出来事です。
簡単な例:
自動販売機の簡単な例です。
自動販売機の関数vending_machineの関数が呼び出された時にTRACEを呼び出します。
計算などの分岐にDEBUGを使っています。
お客さんに関係があるお客の操作の記録はINFOを利用しています。
商品が購入されたらSUCCESSを利用しています。
おつりや在庫が足りないなどは注意が必要だけどまだ処理できる状態なのでWARNIG、
投入金額不足はそれ以上処理ができないエラーなのでERROR、
自動販売機が停止したなどの重大障害はCRITICALです。
from loguru import logger
def vending_machine(action, amount=None):
# TRACE: ボタンが押された瞬間や細かい内部状態の記録
logger.trace(f"アクション開始: {action}, 金額: {amount}")
# DEBUG: 処理の分岐や計算中の細かい情報
if action == "insert_coin":
logger.debug(f"硬貨が投入された: {amount}円")
elif action == "select_item":
logger.debug("商品が選択された")
elif action == "dispense":
logger.debug("商品を出す処理開始")
else:
logger.debug(f"未知の操作: {action}")
# INFO: ユーザーに見える基本的な進捗
if action == "insert_coin":
logger.info(f"{amount}円が投入されました")
elif action == "select_item":
logger.info("商品が選択されました")
elif action == "dispense":
logger.info("商品をお渡しします")
# SUCCESS: 商品が正常に出たときの成功ログ
if action == "dispense":
logger.success("商品が正常に出されました")
# WARNING: おつりが少ない、在庫が少ないなど注意が必要な状況
if action == "select_item" and amount and amount < 100:
logger.warning("投入金額が不足している可能性があります")
# ERROR: 投入金額が足りない場合など、エラー状態
if action == "dispense" and (amount is None or amount < 100):
logger.error("商品を出すには金額が不足しています")
# CRITICAL: 自動販売機のシステムが停止したなどの重大障害
system_ok = True # ここは例です
if not system_ok:
logger.critical("システム障害!即対応必要!")
# 動作例
vending_machine("insert_coin", 100)
vending_machine("select_item")
vending_machine("dispense", 100)
vending_machine("dispense", 50) # エラーの例
出力結果
ロギングファイルの作り方
コンソールに表示だけするのではなくファイルを作る方法もあります。
基本:
logger.add(“作りたいファイルの名前”, level=”記録したいレベル以上のレベル名(大文字)”)
logger.<記録したいログレベル(小文字>(“記録したい記録”)
作りたいファイル名が現在のディレクトリにない場合は自動で作成
ある場合は更新する。
levelで設定したレベル名は、重要度がそのレベル名以上が表示されるようになります。
例:
from loguru import logger
logger.add("test.log", level="INFO")
# ログテスト
logger.debug("DEBUG レベル")
logger.info("INFO レベル(ファイルに追加)")
logger.success("SUCCESS")
logger.warning("WARNING")
logger.error("ERROR")
logger.critical("CRITICAL")
作られたファイル内容
設定をinfoにしているのでinfo以上のレベルがファイルに保存された
コンソール表示
一方でコンソールにはコードに書いたレベル全てが表示されています。
ログの出力先を指定できるadd()
Loguru の add() は ログの出力先(ハンドラー)を追加するメソッド
基本
logger.add(<ログを送る先>, *, level="送りたいレベル以上のレベル",
filter=<条件に合うログだけ通す関数や辞書>)
使い方1, コンソールに表示
logger.add(lambda msg: print(msg, end=""), level="INFO")
INFO 以上をコンソール表示
filter を追加すると特定レベルだけ表示できる
コンソールにINFOだけ表示
デフォルトのコンソール表示を消したいので
logger.remove()
をまず使います。
from loguru import logger
# デフォルトのコンソール出力を削除
logger.remove()
# コンソールに INFO レベルだけ表示
logger.add(lambda msg: print(msg, end=""),
filter=lambda record: record["level"].name == "INFO")
# ログテスト
logger.debug("DEBUG(表示されない)")
logger.info("INFO(コンソールに表示される)")
logger.warning("WARNING(表示されない)")
出力
Infoだけ表示されています。
コンソールに指定した複数のレベルを表示
from loguru import logger
# デフォルトコンソール出力を削除
logger.remove()
# コンソールに DEBUG と WARNING だけ表示
logger.add(
lambda msg: print(msg, end=""), # 標準出力に出す
level="DEBUG", # 最低レベルは DEBUG
filter=lambda record: record["level"].name in ["DEBUG", "WARNING"]
)
# ログテスト
logger.debug("DEBUG(コンソールに表示)")
logger.info("INFO(表示されない)")
logger.success("SUCCESS(表示されない)")
logger.warning("WARNING(コンソールに表示)")
logger.error("ERROR(表示されない)")
logger.critical("CRITICAL(表示されない)")
出力
filter=lambda record: record["level"].name in ["DEBUG", "WARNING"]
[ ]のリストの中に表示したいレベルを追加していけばいいです。
使い方2、 ファイルにログを追加(ロギングファイルですでに言及したがもう一度)
# ログをファイルに出力(デフォルトで追記モード)
logger.add("logfile.log", level="DEBUG") # DEBUG 以上のログを保存
logger.debug("これは DEBUG レベルのログです")
logger.info("これは INFO レベルのログです")
logger.warning("これは WARNING レベルのログです")
logger.error("これは ERROR レベルのログです")
logger.critical("これは CRITICAL レベルのログです")
出力(コンソール)
出力(作ったファイル内)
指定のレベルだけをファイルに保存
from loguru import logger
# デフォルトコンソール出力を削除
logger.remove()
# DEBUG だけを debug.log に保存
logger.add(
"debug.log",
filter=lambda record: record["level"].name == "DEBUG",
encoding="utf-8"
)
# ログテスト
logger.debug("DEBUG(debug.log のみ)")
logger.info("INFO(どのファイルにも保存されない)")
logger.success("SUCCESS(どのファイルにも保存されない)")
logger.warning("WARNING(どのファイルにも保存されない)")
logger.error("ERROR(どのファイルにも保存されない)")
logger.critical("CRITICAL(どのファイルにも保存されない)")
出力
複数の指定したレベルだけをファイルに保存
from loguru import logger
# デフォルトコンソール出力を削除
logger.remove()
# DEBUG と WARNING を logs.txt に保存
logger.add(
"logs.txt",
filter=lambda record: record["level"].name in ["DEBUG", "WARNING"],
encoding="utf-8"
)
# ログテスト
logger.debug("DEBUG(logs.txt に保存)")
logger.info("INFO(保存されない)")
logger.success("SUCCESS(保存されない)")
logger.warning("WARNING(logs.txt に保存)")
logger.error("ERROR(保存されない)")
logger.critical("CRITICAL(保存されない)")
出力
*[合わせ技!] add()の使い方1と2の合わせ技です
ファイルには全レベルを保存、コンソールにはINFOレベルだけ表示
コンソールにはたくさんのログを表示すると、コンソールが文字で埋まってしまいます。
ですがだからといってファイルに保存されないとエラーをチェック出来ないなどの問題があります。
そこでコンソールにはあまり表示しないでファイルには全て保存するという方法を使います。
例
from loguru import logger
# デフォルトのコンソール出力を削除
logger.remove()
# 1. ファイルに全レベルのログを保存
logger.add("logfile.log", level="DEBUG", encoding="utf-8") # DEBUG以上をファイルに保存
# 2. コンソールには INFO レベルのみ表示
logger.add(lambda msg: print(msg, end=""), level="INFO", filter=lambda record: record["level"].name == "INFO")
# ログテスト
logger.debug("DEBUG レベル(ファイルのみ)")
logger.info("INFO レベル(コンソールにも表示)")
logger.success("SUCCESS レベル(ファイルのみ)")
logger.warning("WARNING レベル(ファイルのみ)")
logger.error("ERROR レベル(ファイルのみ)")
logger.critical("CRITICAL レベル(ファイルのみ)")
コンソールの出力
ファイルの出力
クラスでの使い方
mainのクラスで依存関係にあるクラスを複数呼び出す時のloguruの使い方です。
構成はこのようになっています。
MainクラスでSample_1とSample_2クラスを変数で呼び出して依存関係を作った場合です。
その場合基本は、Mainクラスに以下のコードを追加します。
## デフォルト(INFO 以上がコンソールへ)を消す
logger.remove()
# INFO のみ通すコンソール出力を追加
logger.add(
sink=lambda msg: print(msg, end=""),
filter=lambda r: r["level"].name in (“DEBUG”, “INFO”),
colorize=True
)
そして、他のクラスを呼び出します。
# Sample_1クラスの呼び出し
self.sample_1 = Sample_1(self)
# Sample_2クラスの呼び出し
self.sample_2 = Sample_2(self)
Sample_1とSample_2クラスはMainクラスをparentとして呼び出します。
class Sample_1():
def __init__(self, parent):
self.parent = parent
そしてMain関数や他のクラスの好きな所にlogger.info()などを使って、デバッグを呼び出せば完了です。
全体のコード例
from loguru import logger
class Main():
def __init__(self):
logger.remove()
# INFO のみ通すコンソール出力を追加
logger.add(
sink=lambda msg: print(msg, end=""),
filter=lambda r: r["level"].name in ("DEBUG", "INFO"),
colorize=True
)
# mainでデバッグを使う
logger.debug("mainの初期化完了しました。")
# Sample_1クラスの呼び出し
self.sample_1 = Sample_1(self)
# Sample_2クラスの呼び出し
self.sample_2 = Sample_2(self)
class Sample_1():
def __init__(self, parent):
self.parent = parent
print("これはプリント文です")
self.debug_test()
def debug_test(self):
info_1 = "info"
# info文
logger.info(f"インフォ: Sample_1クラス: 関数内の出力{info_1}")
class Sample_2():
def __init__(self, parent):
self.parent = parent
debug_1 = "debug"
# debug文
logger.debug(f"デバッグ: Sample_2クラス: __init__文内の出力{debug_1}")
if __name__ == "__main__":
Main()
出力
クラスをモジュール化した場合
クラスのモジュール化とは、複数のクラスを1つのファイルに詰め込まず、
役割ごとにファイルやクラスを分ける設計の考え方です。
他のファイルに存在するクラスを呼び出す方法は
from <ファイル名(.pyなどは省略)> import <呼び出したいクラス名>
この方法をつかって、loguruを使う場合、
呼び出し側のファイルでは
from loguru import logger
を省略できます。
簡単な例
Log_main.py:
Log_sub.pyを呼び出す側のメインのクラスのモジュールのファイル名です。
Log_sub.py:
呼び出される側の別モジュールのファイル名
Log_main.py
# loguruを呼び出していません
# Log_sub.pyからSubクラスの呼び出し
from Log_sub import Sub
s = Sub()
s.run() # ← main に logger がなくてもログが出る
Log_sub.py
# ここでloguruモジュールを呼び出すことでLog_main.pyにも適用される
from loguru import logger
class Sub:
def run(self):
logger.info("Log_sub.pyのログ")
出力
loguruモジュールをインポートしていないLog_main.pyを実行して、Log_sub.pyのログが表示されました。















