「Pythonで簡単にロギングを行うには」の版間の差分

提供: tknotebook
移動: 案内検索
(構成ファイルを使ったロギング)
(より複雑なロギングを構成する)
66行: 66行:
 
Pythonのロギングの仕組みは log4net や log4j とあまり変わりません。
 
Pythonのロギングの仕組みは log4net や log4j とあまり変わりません。
  
 +
====ロガー====
 
Pythonのロギング では '''「ロガー」''' と呼ばれるオブジェクトの debug とか info 関数を呼ぶことでロギングを行います。
 
Pythonのロギング では '''「ロガー」''' と呼ばれるオブジェクトの debug とか info 関数を呼ぶことでロギングを行います。
 
ロガーはそれに割りつけられた'''「ハンドラ」'''を使ってファイルやコンソールにログを送ります。
 
ロガーはそれに割りつけられた'''「ハンドラ」'''を使ってファイルやコンソールにログを送ります。
  
 +
====ルートロガー====
 
logger には既定の'''「ルートロガー」'''と呼ばれるロガーがあり、ログ出力を行おうとするときに無いと自動的に作られます。
 
logger には既定の'''「ルートロガー」'''と呼ばれるロガーがあり、ログ出力を行おうとするときに無いと自動的に作られます。
 
但し、自動的に作られる'''「ルートロガー」'''は、ハンドラはコンソールに出力するハンドラで、ログレベルが'''WARNING(警告)''' 以上のログ
 
但し、自動的に作られる'''「ルートロガー」'''は、ハンドラはコンソールに出力するハンドラで、ログレベルが'''WARNING(警告)''' 以上のログ
74行: 76行:
  
 
最初に紹介した
 
最初に紹介した
 +
logging.basicConfig(
 +
    level=logging.DEBUG,
 +
    format='%(asctime)s %(levelname)-8s %(module)-18s %(funcName)-10s %(lineno)4s: %(message)s'
 +
)
 +
は強制的にルートロガーを作り、ログレベルがDEBUG以上のログを指定した書式でコンソールに出力するルートロガーを作ります。
 +
 +
====ルートロガー以外のロガーの作り方====
 +
logger = logging.getLogger(<<ロガーの名前>>)
 +
 +
は新しい名前の付いたロガーを作ります。同じ名前を指定して2回呼ぶと、2回目は前と同じロガーの参照が返るので、同じ名前のロガーは1個しか作れません。
 +
 +
'''作られた直後のロガーはハンドラーを持たず、何も出力できませんが、既定でログをルートロガーに転送します。'''ここでの説明ではこの機能だけを利用します。

2018年1月1日 (月) 10:13時点における版

メインページ>コンピュータの部屋#Python>Python Tips

Python は最近山ほど書籍が出ていますが、プログラミングでは必須な ロギング に関する情報がなさすぎなので 簡単なまとめを書いてみることにしました。

最も簡単なやり方

とりあえず

  1. 出力先はコンソールだけ
  2. 適宜出力形式とレベルを変更できるだけでよい

の2条件を満たすだけなら恐ろしく簡単です。

まずメインモジュールの冒頭に以下の import 文を加えます。 

import logging

そしてメインモジュールのモジュールレベルの先頭に

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)-8s %(module)-18s %(funcName)-10s %(lineno)4s: %(message)s'
)

構成ファイルを使ったロギング

通常アプリケーションではもう少し凝ったロギングが必要です。こんな場合を考えてみましょう お置きます。これでお膳立てはおしまいです。

ログを出力するところには以下のように書きます。

 logger.debug("デバッグ")
 logger.info("情報")


出力はコンソールに

2018-01-01 18:09:39,992 DEBUG    main_module        <module>     10: デバッグ
2018-01-01 18:09:39,992 INFO     main_module        <module>     11: 情報

と出力されます。

既にお察しとは思いますが、ログの第一コラムは日付、第2コラムは時刻、第3コラムはログレベル、第4コラムはモジュール名です。

第5コラムは関数名かメソッド名が表示されますが、モジュールレベルでログ出力を呼んだ場合 <module> と出力されます。 第6コラムはモジュール内の行番号、最後がログメッセージです。

メインモジュール以外でロギングを使うときは、先頭に import logging を書き、logger.debug 等でログ出力を書けばOKです。

これだけです。簡単ですよね。


より複雑なロギングを構成する

通常のアプリケーションでは、ロギングにもう少し凝った要件があります。とりあえずこんな条件を考えてみましょう。

  1. ログはコンソールとファイルに出力される。
  2. コンソールには全てのログを出力したい。
  3. ファイルには INFO(情報)以上のレベルのログだけを出力したい。
  4. ログファイルはサイズを 1MB までとし、バックアップファイル3個(つまり合計4個)でローテーションしたい。

これを実現するには3種類のやり方がありますが、その前に、python のロギングの仕組みを簡単に紹介しておきましょう。

Pythonのロギングの仕組み

Pythonのロギングの仕組みは log4net や log4j とあまり変わりません。

ロガー

Pythonのロギング では 「ロガー」 と呼ばれるオブジェクトの debug とか info 関数を呼ぶことでロギングを行います。 ロガーはそれに割りつけられた「ハンドラ」を使ってファイルやコンソールにログを送ります。

ルートロガー

logger には既定の「ルートロガー」と呼ばれるロガーがあり、ログ出力を行おうとするときに無いと自動的に作られます。 但し、自動的に作られる「ルートロガー」は、ハンドラはコンソールに出力するハンドラで、ログレベルがWARNING(警告) 以上のログ しか出力せず、書式も貧弱なので使いずらいです。

最初に紹介した

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)-8s %(module)-18s %(funcName)-10s %(lineno)4s: %(message)s'
)

は強制的にルートロガーを作り、ログレベルがDEBUG以上のログを指定した書式でコンソールに出力するルートロガーを作ります。

ルートロガー以外のロガーの作り方

logger = logging.getLogger(<<ロガーの名前>>)

は新しい名前の付いたロガーを作ります。同じ名前を指定して2回呼ぶと、2回目は前と同じロガーの参照が返るので、同じ名前のロガーは1個しか作れません。

作られた直後のロガーはハンドラーを持たず、何も出力できませんが、既定でログをルートロガーに転送します。ここでの説明ではこの機能だけを利用します。