【Python】loggingモジュールの使い方をコード付きで解説

※本サイトにはプロモーション・広告が含まれています。

(最終更新月:2023年9月)

✔以下のような方へ向けて書かれた記事となります

「Pythonでログを取る方法を知りたい」

「Pythonのloggingモジュールの使い方を学びたい」

「Pythonでのログの実践的な例が見たい」

✔当記事を通じてお伝えすること

  • Pythonでのログ取得の基本
  • loggingモジュールの書き方や応用
  • Pythonを用いたログ取得の実例

当記事では、Pythonでのログ取得の基本から、loggingモジュールを使った応用的な使い方を具体的な例を交えながらわかりやすく解説しています。

最後までお付き合いいただき、Pythonでのログ取得をマスターしてください。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

【副業】ブログ(月間17万PV)/YouTube/Web・アプリ制作

「プログラミング × ライティング × 営業」の経験を活かし、30後半からのIT系職へシフト。当サイトでは、実際に手を動かせるWebアプリの開発を通じて、プログラミングはもちろん、IT職に必要な情報を提供していきます。

【当ブログで紹介しているサイト】

当サイトチュートリアルで作成したデモ版日報アプリ

Django × Reactで開発したツール系Webアプリ

✔人に見せても恥ずかしくないコードを書こう

「リーダブルコード」は、わかりやすく良いコードの定義を教えてくれる本です。

  • 見るからにきれいなコードの書き方
  • コードの分割方法
  • 変数や関数の命名規則

エンジニアのスタンダートとすべき基準を一から解説しています。

何回も読むのに値する本なので、ぜひ手にとって読んでみてください。

Pythonでログを取るための前提知識

当記事では、Pythonプログラミングにおけるログの重要性と、その取り方について詳しくお伝えします。

以下のテーマについて詳しく解説します。

  • ログとは?
  • プログラミングでのログの利点
  • ログの重要性

ログとは?

ログとは、プログラムの実行過程で出力される情報のこと。

適切に取得・管理することでシステムの動作状況を把握したり、問題発生時の原因追求に役立てたりが可能です。

ログは文字情報として出力され、時間や出来事の詳細、重要度(ログレベル)などが記録されます。

プログラミングでのログの利点

プログラミングにおいて、ログを適切に取得・利用することはデバッグやトラブルシューティングにおいて非常に重要です。

エラー発生時の状況を詳細に把握できるので、問題の原因を早期に見つけられます

ログを時間軸に沿って分析し、システムのパフォーマンス監視や、長期的なトレンド分析にも利用可能です。

Pythonプログラミングにおけるログの重要性

Pythonプログラミングにおいて、ログは以下のような用途で欠かせないツールのひとつです。

  • バグの特定
  • パフォーマンスの解析
  • アプリケーションの動作モニタリング

Python標準ライブラリ「logging」とは

こちらでは、Pythonの標準ライブラリであるloggingモジュールについてお伝えします。

ログを扱うために覚えておくべきモジュールです。

  • loggingモジュールとは
  • loggingモジュールの例
  • loggingモジュールの使い方

loggingモジュールの説明

Pythonのloggingモジュールは、プログラムの動作中にログメッセージを出力する、標準ライブラリの一部です。

このモジュールを使用すると、さまざまな重要度のログメッセージを出力できます。

以下がその特徴です。

  1. Logger
    ログの出力を制御する主要なオブジェクト。アプリケーションやライブラリの異なる部分で異なるロガーを持てます。
  2. Handler
    ログメッセージをどこに送るかを決定するオブジェクト。例えば、ログメッセージをコンソールに出力するためのStreamHandlerや、ログメッセージをファイルに書き込むためのFileHandlerなどがあります。
  3. Formatter
    ログメッセージのフォーマットを決定するオブジェクト。例えば、日付、ログの重要度、メッセージ本文などの情報をどのように表示するかを定義します。
  4. Log Record
    ロガーが生成するログメッセージの情報を保持するオブジェクト。
  5. Log Level: ログの重要度を示すレベル。以下のような標準的なレベルがあります。
    • DEBUG
    • INFO
    • WARNING
    • ERROR
    • CRITICAL

loggingモジュールの例

以下は、loggingモジュールを使用した基本的な例です。

import logging

# ログの設定
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# ログの出力
logging.debug('デバッグメッセージ')
logging.info('情報メッセージ')
logging.warning('警告メッセージ')
logging.error('エラーメッセージ')
logging.critical('致命的なエラーメッセージ')

またログメッセージのフォーマットには、以下の情報が含まれています。

  • タイムスタンプ
  • ログレベル
  • メッセージ本文

loggingモジュールは非常に柔軟で、多くの設定やカスタマイズが可能です。

公式ドキュメントや関連するリソースを参照することで、さらに詳しい情報や高度な使用方法を学べます。

loggingモジュールの使い方 (import方法)

loggingモジュールを使用するにはまず、以下のようにimportします。

import logging

ログを出力するためには、以下のような関数を用いることが一般的です。

  • logging.info()
  • logging.warning()
  • logging.error()

例えば、以下のように使用します。

logging.warning('This is a warning message')

上記のコードを実行すると、”WARNING:root:This is a warning message”というメッセージが出力されます。

ログレベルの設定

loggingモジュールでは、ログメッセージに重要度を示すログレベルを設定することが可能です。

ログレベルの詳細な設定方法とその役割について理科を深めましょう。

  • ログレベルとは
  • ログレベルの設定方法とデフォルト設定
  • 独自のログレベルを追加する方法

ログレベルとは

loggingモジュールでは、以下の5つのログレベルが用意されています。

その種類と、目的は以下のとおりです。

  • DEBUG: デバッグ情報。詳細な情報が必要な場合に出力します。
  • INFO: 一般的な情報。システムの動作を追跡するのに役立ちます。
  • WARNING: 何か問題が起こる可能性があるときに出力します。
  • ERROR: 何か問題が起こったときに出力します。
  • CRITICAL: 非常に深刻な問題が起きたときに出力します。

ログレベルの設定方法とデフォルト設定

ログレベルは、loggingモジュールのbasicConfig関数を使って設定可能です。

ここで設定したログレベルが、以降のログ出力全体に適用されます。

以下が例です。

logging.basicConfig(level=logging.DEBUG)
logging.debug('This will get logged')

ログレベルをDEBUGに設定することで、DEBUGレベル以上(DEBUG, INFO, WARNING, ERROR, CRITICAL)の全てのログが出力されます。

なお、basicConfig関数を呼び出さずにログ出力すると、デフォルトのログレベルはWARNINGです。

つまりデフォルトでは、WARNING、ERROR、CRITICALレベルのログのみが出力されます。

独自のログレベルを追加する方法

loggingモジュールでは、5つの基本的なログレベル以外にも、独自のログレベルを追加できます。

これはloggingモジュールのaddLevelName関数を使っておこなうものです。

ただし一般的には、5つの基本的なログレベルを使うことで十分な場合がほとんどです。

LoggerオブジェクトとHandlerオブジェクト

ログの出力設定をより細かく制御するために、loggingモジュールではLoggerオブジェクトとHandlerオブジェクトを提供しています。

それぞれの役割と利用方法について以下で詳しく解説します。

  • Loggerオブジェクトの役割と利用法
  • ハンドラオブジェクトの役割と設定方法

Loggerオブジェクトの役割と利用法

Loggerオブジェクトは、アプリケーションやライブラリのコンポーネントごとに個別のログ出力設定をおこなうためのものです。

特定のモジュールのログレベルを、別のモジュールとは独立に設定する場合に使用します。

Loggerオブジェクトは、loggingモジュールのgetLogger関数で取得しましょう。

引数にはロガーの名前を指定しますが、通常はモジュール名を指定します。

logger = logging.getLogger(__name__)
logger.warning('This is a warning message')

getLogger関数に`name`を指定して、Loggerオブジェクトを取得。

このロガーオブジェクトを使ってログメッセージを出力すると、その出力はこのLoggerオブジェクトの設定に従います。

Handlerオブジェクトの役割と設定方法

Handlerオブジェクトは、ログメッセージをどの出力先(例えば、コンソール、ファイル、メール等)にどのように出力するかを決定します。

複数のハンドラを設定することで、同じログメッセージを複数の出力先に送ることも可能です。

ハンドラオブジェクトの設定は、ロガーオブジェクトのaddHandlerメソッドを用いておこないます。

以下がその例です。

logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.warning('This is a warning message')

上記のコードでは、StreamHandlerを生成し、ロガーオブジェクトに追加しています。

StreamHandlerは、ログメッセージをコンソールに出力するハンドラです。

ログ出力先のカスタマイズ

ログの出力先を自由にカスタマイズする方法について解説します。

  • 標準出力へのログ出力方法
  • ファイルへのログ出力方法(追記モードと上書きモード)
  • 両方の方法を組み合わせる方法

標準出力へのログ出力方法

先ほどのハンドラオブジェクトの設定の例では、StreamHandlerを使用してログメッセージを標準出力に出力しました。

これは一番基本的なログの出力方法であり、デバッグ時などによく使われます。

logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.warning('This is a warning message')

上記のコードを実行すると、「This is a warning message」というメッセージがコンソールに出力されます。

ファイルへのログ出力方法(追記モードと上書きモード)

ログメッセージをファイルに出力するには、FileHandlerを使用します。

FileHandlerは初期化時に出力先のファイル名を引数として取ります。

また、第二引数にはファイルの開き方を指定することができ、’a’を指定すると追記モード、’w’を指定すると上書きモードになります。

以下に例を示します。

logger = logging.getLogger(__name__)
handler = logging.FileHandler('my_log.log', 'a')
logger.addHandler(handler)
logger.warning('This is a warning message')

「This is a warning message」というメッセージがmy_log.logという名前のファイルに出力。

第二引数で’a’を指定しているため、同じコードを何度も実行しても、メッセージはファイルに追記されていきます。

‘w’を指定した場合は、コードを実行するたびにファイルが上書きされます。

両方の方法を組み合わせる方法

複数のハンドラを同時に設定することで、同じログメッセージを標準出力とファイルの両方に出力することも可能です。

以下に例を示します。

logger = logging.getLogger(__name__)
stream_handler = logging.StreamHandler()
file_handler = logging.FileHandler('my_log.log', 'a')
logger.addHandler(stream_handler)
logger.addHandler(file_handler)
logger.warning('This is a warning message')

上記のコードを実行すると、「This is a warning message」というメッセージがコンソールに出力されるとともに、my_log.logという名前のファイルにも出力されます。

ログ出力の設定やカスタマイズにより、さまざまな状況に対応できるでしょう。

ログフォーマットのカスタマイズ

この節では、ログフォーマットのカスタマイズ方法についてお伝えします。

  • ログの見やすさについて
  • ログフォーマットの要素
  • ログフォーマットの設定方法

ログの見やすさについて

ログのフォーマットは、プログラムの動作を理解しやすくするための重要な要素です。

なぜならログが見やすくなければ、プログラムの動作を追跡するのが難しくなるからです。

読みやすさと解釈のしやすさを向上させるためにカスタマイズすることが推奨されます。

ログフォーマットの要素

ログフォーマットは一般的に、以下で構成されます。

  • 日付
  • 時間
  • ログレベル
  • メッセージ
  • 発生源のファイル名

これらの要素は必要に応じて自由に組み合わせられ、それぞれが異なる情報を提供してプログラムの動作を理解しやすくします。

ログフォーマットの設定方法

Pythonのloggingモジュールでは、ログフォーマットを設定するためのFormatterクラスが提供されています。

Formatterクラスにより、自由な形式でログメッセージが作成可能。

以下に例を示します。

logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.warning('This is a warning message')

出力は以下のとおりです。

2023-07-28 12:34:56,789 - __main__ - WARNING - This is a warning message
  • %(asctime)s:出力時刻、
  • %(name)s:ロガーの名前
  • %(levelname)s:ログレベル
  • %(message)s:ログメッセージ

自由に組み合わせられるので、多くの属性がloggingモジュールによって提供されています。

スレッドセーフ性とLoggerAdapterオブジェクト

こちらでは、Pythonでのログ取り扱いにおけるスレッドセーフ性とLoggerAdapterオブジェクトの利用法について解説します。

  • スレッドセーフ性について
  • LoggerAdapterオブジェクトの利用方法とメリット

スレッドセーフ性について

Pythonのloggingモジュールは、マルチスレッド環境で安全に使用できます。

複数のスレッドが同時にログを出力する場合でも、それらのログメッセージは適切に処理され、予期せぬ問題を引き起こすことはありません。

プログラムのデバッグや問題の特定を容易にするために重要な特性です。

LoggerAdapterオブジェクトの利用方法とメリット

LoggerAdapterオブジェクトは、ログメッセージに追加情報を付与するための便利なツールです。

各ログメッセージにコンテキスト情報を追加して出力することが可能となります。

以下に使用例を示します。

class ContextFilter(logging.Filter):
    def filter(self, record):
        record.ip = '123.456.789.012'
        return True

logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(ip)s - %(message)s')
handler.setFormatter(formatter)
logger.addFilter(ContextFilter())
logger.addHandler(handler)
logger.warning('This is a warning message')

このコードを実行すると、以下のような出力が得られます。

2023-07-28 12:34:56,789 - __main__ - WARNING - 123.456.789.012 - This is a warning message

ここで、%(ip)sは新しく追加した情報(ここではIPアドレスを模擬)を表します。

このように、LoggerAdapterを使うと各ログメッセージに独自の情報を付け加えられ、ネットワーク環境やマルチユーザー環境で役立つのです。

warningsモジュールとの連携

こちらでは、「warnings」モジュールについてお伝えし、それがPythonのloggingモジュールとどのように連携するのかを説明します。

  • warningsモジュールの紹介
  • loggingとwarningsモジュールを組み合わせる方法

warningsモジュールの紹介

Pythonのwarningsモジュールは、警告メッセージを出力するためのツールです。

警告はエラーではなく、通常のプログラムの実行を中止しないメッセージです。

以下のようなものを対象に用いられます。

  • 何か問題が発生しそうな事象
  • 非推奨の関数の使用や将来的に予期せぬ動作を引き起こす可能性のあるコード

loggingとwarningsモジュールを組み合わせる方法

warningsモジュールとloggingモジュールは組み合わせて使用できます。

警告をloggingモジュール経由で出力することにより、以下のようなことが可能です。

  • 警告メッセージの出力先を自由に指定
  • フォーマットを自由に設定
  • 警告メッセージを記録

以下に、warningsモジュールの警告をloggingモジュールを通じて出力する簡単な例を示します。

import warnings
import logging

# warningsのshowwarning()を上書き
def custom_showwarning(message, category, filename, lineno, file=None, line=None):
    logging.warning('%s:%s: %s: %s' % (filename, lineno, category.__name__, message))

warnings.showwarning = custom_showwarning

# これは警告を生成します
warnings.warn('This is a warning message')

warnings.warn()が呼び出されると、警告メッセージがlogging.warning()を使って出力されるもの。

このようにして、loggingモジュールの全ての機能を利用して、警告をより効果的に制御することが可能となります。

実践編: Pythonプロジェクトでのloggingの活用

こちらでは、実際のPythonプロジェクトにおけるloggingモジュールの活用について説明します。

特に、エラー処理や全体のログ設定に焦点を当てて見ていきましょう。

  • サンプルコードの説明
  • loggingモジュールを使ったエラー処理の実例
  • プロジェクト全体で統一されたログ設定の方法

サンプルコードの説明

次のようなシンプルなPythonコードを考えてみましょう。

このコードは、データ処理を模擬したものです。

def process_data(data):
    print("Processing data...")
    # 何かしらの処理
    # ...
    print("Data processing completed.")

process_data("Sample data")

このコードは機能的には問題ありませんが、問題が発生したときに対処する方法がありません。

また、デバッグやトラブルシューティングに必要な情報が不足しています。

loggingモジュールを使ったエラー処理の実例

ここで、このコードをloggingモジュールを使って改善してみましょう。

import logging

logging.basicConfig(level=logging.INFO)

def process_data(data):
    logging.info("Processing data...")
    try:
        # 何かしらの処理
        # ...
    except Exception as e:
        logging.error("Error occurred while processing data: %s", e)
        raise
    logging.info("Data processing completed.")

process_data("Sample data")

このコードは、処理中に何が起こっているかをログに記録し、処理中にエラーが発生した場合にはその情報もログに記録します。

これにより、エラーが発生した原因を調査しやすくなります。

プロジェクト全体で統一されたログ設定の方法

大規模なプロジェクトでは、すべてのモジュールで統一されたログ設定を使用することが重要です。

これを達成するひとつの方法は、専用の設定ファイルを作成し、プログラムの開始時にそれを読み込むこと

以下に例を示します。

import logging.config

logging.config.fileConfig('logging.conf')

# これ以降、loggingは設定ファイルに基づいて動作します

まとめ

当記事では、Pythonでのログ取得についてお伝えしてきました。

  • ログは、プログラムの実行中に何が起こったのかを記録し、エラーが発生したときの原因分析やパフォーマンスの調査に役立つ重要なツール
  • Pythonの標準ライブラリに含まれるloggingモジュールを使用することで、Pythonプログラムに簡単にログ機能を追加できる
  • ログレベルの設定、ログ出力先のカスタマイズ、ログフォーマットの変更など、詳細な設定も可能

当記事があなたのPythonでのログ取得に対する理解を深める一助となれば幸いです。

タイトルとURLをコピーしました