【Python】自作ライブラリにロガーを追加するコード例 NullHandler

Python で自作ライブラリ(自作モジュール)にロガーを追加するコード例です。

自作ライブラリのロガーには、NullHandlerナル ハンドラ が便利でした。

これで、『メインモジュール』がロガーを『使ったとき』にだけ、『自作ライブラリ』のログを出力することができました。

また、『メインモジュール』がロガーを『使わなかったとき』は、『自作ライブラリ』のログが『まったく』出ない、という状態にすることができました。

ところで、NullHandler を追加しなくても、プログラムがエラーで止まったりすることは無かったです。

しかしながら、深刻なログレベルについては、ロガー無しで呼び出しているときでも、出力されました。

NullHandler は、必要に応じて追加すればよいと思います。

使用したライブラリ

Python 公式マニュアルの場所です。

logging モジュール

logging.handlers パッケージ

組み込み機能

コード例

コードは、『メインモジュール』と『自作ライブラリ』の2つです。

まずは、自作ライブラリを使うための『メインモジュール』コードです。

ロガーは『ルートロガー』を使います。

自作ライブラリを import して、その中の関数を使います。

""" 1/2 StreamHandlerでログ出力するPythonコード例
app_main.py (application main)"""

import logging

# ルートロガーを取得
lg = logging.getLogger(name=None)
lg.setLevel(logging.DEBUG)

# ストリームハンドラを取得 & ロガーに追加
sh = logging.StreamHandler()
sh.setFormatter(logging.Formatter(
    '%(levelname)s %(name)s: %(funcName)s() %(message)s'))
sh.setLevel(logging.DEBUG)
lg.addHandler(sh)
del sh

from app_lib import log_check_text

def main():
    """メイン関数"""
    lg.debug('start')

    # 自作ライブラリを使う
    log_check_text('あかさたな')

    # 自作ライブラリを使う
    log_check_text(12345)

    lg.debug('end')
    return

if __name__ == '__main__':
    main()

次に、『自作ライブラリ』のコードです。

ロガーには名前を付けます。なので、こちらはルートロガーではないです。

ハンドラは、ナルハンドラ NullHandler() を追加します。

""" 2/2 自作ライブラリ (NullHandler使用)
app_lib.py (application library)"""

import logging
lib_lg = logging.getLogger(name=__name__)
lib_lg.addHandler(logging.NullHandler())

def log_check_text(text):
    """変数の種類をチェックする関数"""

    if isinstance(text, str):
        lib_lg.info(f'OK 引数は有効 {type(text)}')
    else:
        lib_lg.warning(f'NG 無効なタイプの引数 {type(text)}')
    return

実行結果

『メインモジュール』から『自作ライブラリ』を呼び出した実行結果です。

DEBUG root: main() start
INFO app_lib: log_check_text() OK 引数は有効 <class 'str'>
WARNING app_lib: log_check_text() NG 無効なタイプの引数 <class 'int'>
DEBUG root: main() end

自作ライブラリが出力したログ(app_lib の行)を表示することができました。

ロガーを使わずに自作ライブラリを呼び出した結果

『自作ライブラリ』を使うときに、ロガーを使わなかったときの実行結果です。

ロガー無しのコード例

『メインモジュール』から、ロガーを削除しました。

ロガーを使っていないので、画面には何も出力しないで欲しいところです。

""" 1/2 『ロガー無し』でライブラリを使うだけのPythonコード例
app_main.py (application main)"""

from app_lib import log_check_text

def main():
    """メイン関数"""

    # 自作ライブラリを使う
    log_check_text('あかさたな')

    # 自作ライブラリを使う
    log_check_text(12345)

    return

if __name__ == '__main__':
    main()

『自作ライブラリ』のコードは同じです。変更無しです。

""" 2/2 自作ライブラリ (NullHandler使用)
app_lib.py (application library)"""

import logging
lib_lg = logging.getLogger(name=__name__)
lib_lg.addHandler(logging.NullHandler())

def log_check_text(text):
    """変数の種類をチェックする関数"""

    if isinstance(text, str):
        lib_lg.info(f'OK 引数は有効 {type(text)}')
    else:
        lib_lg.warning(f'NG 無効なタイプの引数 {type(text)}')
    return

実行結果

呼び出し側が、ロガー無しで『自作ライブラリ』を使った結果です。

意図した通り、画面には何も表示されませんでした。

(出力なし)

ロガーを使わないとエラーが発生する、といったことも無かったです。

成功です。

『自作ライブラリ』の利用者が、ロガーを使っていても、使っていなくても、うまく動作しました。

NullHandler を使わなかった時の実行結果

『自作ライブラリ』で、ロガーにナルハンドラ NullHandler を追加しなかったときの実行結果です。

NullHandler 無しのコード例

ロガー無しの『メインモジュール』です。

ロガーを使っていないので、画面には何も出力しないで欲しいところです。

""" 1/2 『ロガー無し』でライブラリを使うだけのPythonコード例
app_main.py (application main)"""

from app_lib import log_check_text

def main():
    """メイン関数"""

    # 自作ライブラリを使う
    log_check_text('あかさたな')

    # 自作ライブラリを使う
    log_check_text(12345)

    return

if __name__ == '__main__':
    main()

『自作ライブラリ』のコードです。

NullHandler を削除しました。

その結果、ハンドラ無しのロガーを使っています。

""" 2/2 自作ライブラリ (NullHandler無し)
app_lib.py (application library)"""

import logging
lib_lg = logging.getLogger(name=__name__)
# NullHandler無し

def log_check_text(text):
    """変数の種類をチェックする関数"""

    if isinstance(text, str):
        lib_lg.info(f'OK 引数は有効 {type(text)}')
    else:
        lib_lg.warning(f'NG 無効なタイプの引数 {type(text)}')
    return

実行結果

NullHandler 無しで作った『自作ライブラリ』を、ロガー無しで呼び出した結果です。

『メインモジュール』でロガーを使わなかったので、画面には何も表示されないで欲しいところです。

ところが、一部のログだけ、画面に表示されました。

NG 無効なタイプの引数 <class 'int'>

これは、ウォーニングレベル .warning() で出力したログでした。

インフォレベル .info() のログは出なかったのに、ウォーニングレベル .warning() は出力されました。

Python 公式マニュアルによると、深刻なレベルのログについては、ログを出すようにしているとのことでした。

使っているアプリケーションがロギングを使っていなくて、ライブラリコードがロギングを呼び出すと、(前の節で解説したように) 重大度 WARNING 以上のイベントが、sys.stderr に表示されます。これが最高のデフォルトの振る舞いと見なされます。

ライブラリのためのロギングの設定

そういったログも含めて、出さないようにしてくれるのが『ナルハンドラ NullHandler』ということでした。

結局、NullHandler は必要に応じて追加することになりました。

ロガーを使うならログを出す、ロガーを使わないなら完全に出さない。
⇒ 自作ライブラリのロガーに『NullHandler』を追加する。

ロガーを使っていないときでも、深刻なログは出す。
⇒ 自作ライブラリのロガーに『ハンドラ無しのロガー』を使う。

スポンサーリンク
Python評価
シェアする(押すとSNS投稿用の『編集ページ』に移動します)
フォローする(RSSフィードに移動します)
スポンサーリンク
シラベルノート
タイトルとURLをコピーしました