Django Python

[Python実践]Loggingに挑戦してみよう!《基礎編》〜公式ドキュメントをもとに解説〜

cardene

こんにちは!実務でPython、Djangoを使って、機械学習やWebアプリケーションの開発をしているかるでねです!

今回はPythonの「Logging」の基礎について解説していこうと思います!

応用編はこちらにになります。

Logging」はPythonの実務などでよく使われるので、Pythonエンジニアを目指している方は是非この記事でマスターしていってください!

この記事はPythonの公式ドキュメントを参考にしています。

Pythonに限らず、プログラミング言語の公式ドキュメントは非常に読みにくいので、この記事でわかりやすく解説していきます。

Loggingよく見かけるんだけど全くわからない...

Pythonエンジニアを目指して学習中

Pythonスキルのレベルアップをしたい!

このような人のお役に立てれば幸いです。

それでは早速本題に入っていきましょう!

「Logging」はPythonの基礎を理解していないと難しいので、Pythonの基礎を理解していない人は以下を参考に学習してください!

Amazon

入門 Python 3

概要

まずは「Logging」がどういったものなのかなどの概要から見ていきましょう。

Logging」とは以下のようなものです。

ポイント

  • プログラムが実行されているときに起こったイベントを追跡してくれる。
  • 重要度を設定して、特定のイベントが発生したことをメッセージと共に知らせてくれる。

この説明だけでは理解できないと思うので、この記事を通して理解していってください!

用途

Logging」の概要を見てきましたが、実際どのような場面で使用されるのでしょうか?

ポイント

  • プログラム実行中に発生した状態の監視や障害の分析。
  • 特定の動作に関する警告やエラーの警告。

上記のような場面で主に使われます。

例外処理との違い

もしかしたら「例外処理とどう違うの?」と思う人がいるかもしれないです。

なのでここで2つの違いを解説していきます。

まずは用語の整理からしていきましょう。

まずは「例外処理」から。

想定内のエラーの処理。

次に「Logging」。

記録を取る。

こうみるとずいぶん違いますね。

Logging」はその名の通り「ログ」をとっているイメージですね。

記録を取ることで「エラーが起きそうか。」や「エラーが起きていないか。」、「動作の確認」などを行うことができます。

一方「例外処理」は、「エラーが起きたときにどうするか」を行うだけなので違いがよく分かりますね。

重要度レベル

概要の説明の部分で、「重要度を設定して...」とありました。

ここではその「重要度」について解説していきます。

重要度」は以下の5つで、下にいくほど重要です。

ポイント

  • DEBUG
  • INFO
  • WARNING
  • ERROR
  • CRITICAL

1つ1つ特徴を見ていきましょう!

DEBUG

問題を診断し、詳細な情報を確認する。

INFO

想定された通りのことが起こったことの確認。

WARNING

想定外のことが起こった、もしくは問題が起こりそうであることを知らせてくれる。

ERROR

より重大な問題により、ソフトウェアがある機能を実行できない。

CRITICAL

プログラム自体が実行を続けられないことを表す、重大なエラー。

以上のような特徴があるので、なんとなく理解しておきましょう。

デフォルトLevel

Level」とは先ほどの「重要度」のことです。

この「Level」にはデフォルトレベルがあります。

このデフォルトレベル以上の「Level」が出力されます。

このデフォルトレベルは「WARNING」です。

では早速コードで確認してみましょう!

import logging

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

# WARNING:root:Warningだよ!!!
# ERROR:root:Errorだよ!!!
# CRITICAL:root:Criticalだよ!!!

出力を確認してみると「Warning」以上のメッセージが出力されていますね。

では「Level」を変更してみましょう。

logging.basicConfig(level=logging.ERROR)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

# ERROR:root:Errorだよ!!!
# CRITICAL:root:Criticalだよ!!!

1行目の部分で「Error」にレベルを設定してから出力を確認してみると、しっかり「Error」以上のメッセージが出力されていますね。

ファイル出力

前章で「Logging」の概要を確認できました。

では次に出力結果をファイルに格納してみましょう。

実行

まずはとりあえず試してみましょう。

import logging

logging.basicConfig(filename='logging.log', encoding='utf-8', level=logging.DEBUG)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

3行目を詳しくみていきましょう。

logging.basicConfig(filename='logging.log', encoding='utf-8', level=logging.DEBUG)

filename」で出力先のファイル名を指定しています。

encoding」では、出力の文字コードを指定しています。(なくても平気です。)

level」では、前章で説明した重要度を指定しています。(今回は「DEBUG」を指定しているので、全て出力されます。)

では出力を確認していきましょう。

logging.log」ファイルを開くと以下のように出力されています。

DEBUG:root:Debugだよ!
INFO:root:Infoだよ!!
WARNING:root:Warningだよ!!!
ERROR:root:Errorだよ!!!!
CRITICAL:root:Criticalだよ!!!!

ちゃんと全部出力されていますね。

レベル変更

では次に出力レベルを変更してみましょう。

レベルを「Warning」に指定してみます。

import logging

logging.basicConfig(filename='logging.log', encoding='utf-8', level=logging.WARNING)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

では出力を確認してみます。

WARNING:root:Warningだよ!!!
ERROR:root:Errorだよ!!!!
CRITICAL:root:Criticalだよ!!!!

予想通り「Warning」以上のレベルのメッセージが気出力されていますね。

この「level」が閾値となって、そレベル以上のメッセージが出力されるように設定できます。

上書きに変更

現状だと「logging.log」に「追記」されていってしまうので、「上書き」に変更してみましょう。

import logging

logging.basicConfig(filename='logging.log', filemode='w', encoding='utf-8', level=logging.WARNING)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

filemode」で「w」と指定することで「上書き」に変更できます。

逆に明示的に「追記」を指定してみましょう。

import logging

logging.basicConfig(filename='logging.log', filemode='a', encoding='utf-8', level=logging.WARNING)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

filemode」を「a」に設定することで「追記」にできます。

機械学習について学ぶならこちら!

複数ファイルのロギング

次に別のファイルで定義された「Logging」を呼び出して使用してみましょう。

まずはメインで使用しているファイルを用意します。

import logging
import test # 他のファイル

def main():
    logging.basicConfig(filename='logging.log', level=logging.INFO)
    logging.info('Start!このファイルのInfoだよ!!')
    test.log_warning()
    logging.error('End!このファイルのErrorだよ!!!!')

if __name__ == '__main__':
    main()

2行目で「test.py」というファイルを読み込んで、7行目で「test.py」ファイルの「log_warning」関数を呼び出しています。

5行目を確認すると「Info」レベル以上のメッセージを「logging.log」に出力するように指定しています。

では「test.py」ファイルを確認してみましょう。

import logging

def log_warning():
    logging.warning('他のファイルのWarningだよ!!!')

4行目でログ出力メッセージを定義しています。

では「main.py」の方を実行してみましょう。

INFO:root:Start!このファイルのInfoだよ!!
WARNING:root:他のファイルのWarningだよ!!!
ERROR:root:End!このファイルのErrorだよ!!!!

Info」以上のメッセージが出力されていますね!

変数をロギング出力

メッセージの中に変数を格納して出力してみましょう。

import logging

message = "かるでねブログ"

logging.warning(f'{message} !!!')
# WARNING:root:かるでねブログ !!!

これはPythonの基礎知識ですが改めて確認していきましょう!

f"{}"」の「{}」の中に変数を格納することで、変数と文字列をくっつけて出力してくれます。

他にもこのようなしても同じことができます。

message = "かるでねブログ"

logging.warning('{} !!!'.format(message))
# WARNING:root:かるでねブログ !!!

logging.warning(f'%s !!!' % message)
# WARNING:root:かるでねブログ !!!

3行目では、文字列の中に「{}」だけを入れて、文字列の後ろで「{}」に何を入れるかを指定しています。

6行目の方では、文字列の中に「%s」を入れて、文字列の後ろで、「%s」に何を入れるかを指定しています。

どれを使ってもいいですが、比較的短い「f"{}"」か「%s」を使用できるといいですね。

表示メッセージをカスタマイズ

表示メッセージの中身だけは指定できますが、「WARNING:root:」のような部分は今のところ変更できていません。

この部分を自分が見やすいようにカスタマイズしていきましょう!

基本的なやり方

ちょっとコードが長くなりますが、基本的な使い方を確認してみましょう。

import logging

logging.basicConfig(filename='logging.log', format="%(levelname)s → %(message)s",
					encoding='utf-8', level=logging.WARNING)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

ほとんどはこの章よりも前に確認できているはずです。

では出力を確認してみます。

WARNING → Warningだよ!!!
ERROR → Errorだよ!!!!
CRITICAL → Criticalだよ!!!!

前回と出力が変わっていますね。

これは「format」の部分で指定しています。

3行目の「format」では、「"%(levelname)s → %(message)s"」と指定されているので解説していきます。

levelname」は、「INFO」や「ERROR」などのレベル名のことです。

message」は、自分で指定したメッセージのことです。

このように自分が見やすいようにカスタムすることができます。

この部分に使用できる変数はこちらに一覧となっているので確認してみてください。

https://docs.python.org/ja/3/library/logging.html#logrecord-attributes

時刻表示

先ほどの一覧ページを確認して、その中の1つである「時刻表示」を試していきたいと思います。

import logging

logging.basicConfig(filename='logging.log', 
					format="時刻: %(asctime)s %(levelname)s → %(message)s",
					encoding='utf-8', level=logging.WARNING)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

4行目で、「"時刻: %(asctime)s..."」と指定することで時刻を表示できます。

出力を確認してみましょう。

時刻: 2022-02-19 11:25:30,170 WARNING → Warningだよ!!!
時刻: 2022-02-19 11:25:30,170 ERROR → Errorだよ!!!!
時刻: 2022-02-19 11:25:30,170 CRITICAL → Criticalだよ!!!!

実行した時刻を表示できましたね。

時刻表示をカスタマイズ

最後に「時刻表示」自体をカスタマイズして、もっとみやすくしましょう。

import logging

logging.basicConfig(filename='logging.log', 
                    format="時刻: %(asctime)s %(levelname)s → %(message)s",
                    datefmt='%m/%d/%Y %I:%M:%S %p',
					          encoding='utf-8', level=logging.WARNING)

logging.debug('Debugだよ!')
logging.info('Infoだよ!!')
logging.warning('Warningだよ!!!')
logging.error('Errorだよ!!!!')
logging.critical('Criticalだよ!!!!')

5行目の「datefmt」で表示方法を指定しています。

では出力結果を確認してみましょう。

時刻: 02/19/2022 11:26:56 AM WARNING → Warningだよ!!!
時刻: 02/19/2022 11:26:56 AM ERROR → Errorだよ!!!!
時刻: 02/19/2022 11:26:56 AM CRITICAL → Criticalだよ!!!!

前回と表示が変わりましたね。

これで「Logging」の基礎部分は完璧です!

機械学習について学ぶならこちら!

最後に

今回は「Logging」の基礎について解説してきました。

いかかだったでしょうか?

Logging」出力を自分好みにカスタマイズできるまでレベルアップできたはずです。

応用編の記事も用意しているので、体力がある方はぜひ!

普段はPythonやブロックチェーンメインに情報発信をしています。

Twiiterでは図解でわかりやすく解説する投稿をしているのでぜひフォローしてくれると嬉しいです!

-Django, Python
-,