📝

Pythonのloggingをイメージで理解する【Python Logging徹底解説】

2023/03/26に公開

記事を書いた背景

最近業務で業務効率化のオンプレwebアプリケーションや自動化プログラムを作成する機会増えているが、特に自動化プログラムにおいてlogという存在の重要性をより強く感じている。
作成したアプリケーションやシステムの数が増えるほど、個々の動作確認に割くことができる工数が限られてくるため、より分かりやすいフォーマットで効率よくログ収集する必要がある。
この記事では、Pythonにおけるloggingを"イメージ重視"でわかりやすく解説していく。

この記事の想定読者

  • Python "Logging HOWTO"の基本loggingチュートリアルを読んだことがある人
  • Pythonのシステムにしっかりとカスタマイズしたlogを組み込みたい人
  • Pythonのloggingを用いてターミナル等に簡単なlogを出力できる人
  • loggingを触ったことが無い人
  • Python Loggingをイメージで理解したいと考えている人

print文

Pythonにおいてターミナル出力といえば真っ先にprint文が想起される。
実際公式チュートリアルにも以下のように記述されている通り、最もシンプルかつベーシックなログ出力方法がprint文と言える。

行いたいタスク そのタスクに最適なツール
コマンドラインスクリプトやプログラムで普通に使う、コンソール出力の表示 print()

即ち、最も簡単なログ出力は以下の通りとなる。

sample1.py
# print文によるターミナルへのログ出力
print("I am the simplest log.")
terminal
# 実行結果
>>> I am the simplest log

printとloggingの違い

「プログラムがその場所を通過したかどうかをターミナルに出力したい」程度であればprint文で十分だが、実際のところloggingに求める機能としては以下の例のようなものが挙げられるだろう。

  • 開発者が見ていない間もファイルに出力・記録しておきたい
  • 特定のエラーが起こったらシステム管理者のアドレスにメールを飛ばしたい
  • 発生したログ情報をその都度HTTP通信で送信したい(slackに通知したい等)

このように、プログラムの動作ログをよりフレキシブルに出力したい場合には、Pythonに予め用意されているloggingモジュールを使用してログを出力する。

ログレベルと出力関数

printによってターミナルに出力されるログはログメッセージのみを持っているが、loggingによって出力されるログには、発生日時発生場所ログレベル等の様々なデータが含まれている。

ログレベル

loggingによって出力されるログには、そのログの発生事由の"重大度(ヤバさ)"に応じて以下のようなレベルが設定される。

レベル いつ使うか
DEBUG おもに問題を診断するときにのみ関心があるような、詳細な情報。
INFO 想定された通りのことが起こったことの確認。
WARNING 想定外のことが起こった、または問題が近く起こりそうである (例えば、'disk space low') ことの表示。
ERROR より重大な問題により、ソフトウェアがある機能を実行できないこと。
CRITICAL プログラム自体が実行を続けられないことを表す、重大なエラー。

出力関数

ログレベルについて確認したところで、loggingを用いた出力の最も簡単な例を以下に示す。

sample2.py
# loggingモジュールのインポート
import logging

# infoレベルでのログ出力
logging.info("I am info log.")
# warningレベルでのログ出力
logging.warning("I am warning log.")
terminal
# 実行結果
>>> I am warning log.

上記コードではloggingモジュールをimportし、必要なレベルに応じた関数を実行することによって、レベルを指定してログを出力できるという仕組みになっている。
上記コードのように何も設定しないまま出力しようとすると、WARNINGメッセージは出力されたがINFOメッセージは出力されていないことが分かる。
これはloggingモジュールにおいて、デフォルトの最低出力レベルがWARNINGに設定されているからである。

loggingのイメージ

loggingの設定等の説明に入る前に、loggingのイメージを図を用いて示しておく。

まずは上の図に従って、次のようなイメージを持ってほしい。

  1. loggingはログ出力を行う人(または人型ロボット)である
  2. loggingは1つのpython.exeに対して1人のみ存在する
  3. 図のようにpython.exeを用いてプログラムを実行するSystem-Aがあるとする
  4. System-Aで必要なログ出力設定(Handler)をloggerに渡し、loggerはその設定ハンドラに従ってログを出力する
  5. loggingは複数のハンドラを保持することができる

loggingは直接使用禁止!

先の例ではloggingに対して直接メソッドを指定して実行したが、実際の使用時ではこれはNGである。理由は先のイメージのうち25に関連しており、その点について以下で解説を行う。

前提として、dockerやpipenv、複数のバージョンのpythonを上手く使い分けていない限り、基本的にPCには一つのpython.exeしか存在しない。

2. loggingは1つのpython.exeに対して1人のみ存在する
5. loggingは複数のハンドラを保持することができる

この25の性質より、複数のシステムで1つのpython.exeを使用していた場合、loggingは図のように異なるシステムのハンドラ(設定)を複数持つこととなり、あるシステムで設定したハンドラが別のシステムのハンドラにも影響を及ぼす等、思わぬバグを生む原因となる。

ログ出力にはloggerを使用しよう!

では実際どのようにloggingを用いればよいのか。結論から言うと、loggingと同等の機能を持った子供(のようなイメージ)であるloggerオブジェクトを必要な分作って用いればよい。

loggerオブジェクトでのログ出力

ここで、loggerオブジェクトを取得し、ターミナルにログを出力する部分のコードを示す。

sample3.py
import logging

# loggerオブジェクトの作成
logger = logging.getLogger("ログ太郎")

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
# 実行結果
>>> I am warning log.

loggerオブジェクトを取得するには、loggingモジュールのgetLogger関数を用いる。引数は1つで、loggerの名前を文字列で引き渡す。ここでは"ログ太郎"という名前のloggerが生成されている。
loggerオブジェクトを用いたログの出力方法は、ログレベル毎に用意されたメソッドを叩くことで実行される。また実行結果をみるとわかる通り、loggerオブジェクトによるログ出力も、デフォルトの最低出力設定がWARNINGとなっていることがわかる。

loggerからの出力レベルの設定

loggerからの出力レベルはデフォルトでwarning以上であると述べたが、必要に応じてその最低出力レベルを変更したい場面が多々ある。以下ではその設定方法を示す。

sample4.py
import logging
logger = logging.getLogger("ログ太郎")

# ログ太郎からの最低出力レベルをDEBUGに設定
logger.setLevel(logging.DEBUG)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
>>> I am info log.
>>> I am warning log.

loggerオブジェクトのsetLevelメソッドを用いて、ログ太郎の最低出力レベルをDEBUGに設定している。このsetLevelメソッドの引数に渡すオブジェクトは、loggingモジュール内のDEBUG定数であり、DEBUGの中身には10というint型の値が入っている。これは各レベルに対して以下のような数値が与えられているためである。

レベル名 数値
DEBUG 10
INFO 20
WARNING 30
ERROR 40
CRITICAL 50

基本的にはlogger.setLevel(logging.DEBUG)のように、loggingモジュール内の定数を用いてsetLevelメソッドを実行するが、意味合い的にはlogger.setLevel(10)と全く同じである。

sample5.py
import logging
logger = logging.getLogger("ログ太郎")

# ログ太郎からの最低出力レベルを10(=DEBUG)に設定
logger.setLevel(10)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
>>> I am info log.
>>> I am warning log.

ハンドラのイメージ

ここからは、loggingやloggerのイメージ説明の際に出てきたハンドラについて解説する。
ハンドラとは、loggerがログ出力の際に使用する道具のようなもので、以下のような種類のハンドラが用意されている。(一部抜粋)

ハンドラインスタンス loggerに付与される機能
StreamHandler ターミナルへの出力
FileHandler ファイルへの出力
SMTPHandler 特定のメールアドレスへの送信出力
HTTPHandler HTTPサーバへの出力

> Logging HOWTO 便利なハンドラ

ここでは最も頻繁に使用されるStreamHandlerとFileHandlerを例に挙げて説明する。

それぞれのハンドラに対して、図のように以下のイメージを持ってほしい。

  • StreamHandler: ターミナルを通して開発者にログを届けるスピーカー
  • FileHandler: ログをファイルに書き留めておくためのペンと紙

loggerにこれらの道具を渡しておくことで、loggerはこの道具を使用してログを出力してくれるようになる。
ではまず実際に道具を持たせる部分のコードを示す。

sample6.py
import logging
logger = logging.getLogger("ログ太郎")
logger.setLevel(logging.DEBUG)

# Streamハンドラクラスをインスタンス化
st_handler = logging.StreamHandler()
# Fileハンドラクラスをインスタンス化
fl_handler = logging.FileHandler(filename="sample6.log", encoding="utf-8")
# インスタンス化したハンドラをそれぞれログ太郎に渡す
logger.addHandler(st_handler)
logger.addHandler(fl_handler)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
# 実行結果
>>> I am info log.
>>> I am warning log.
sample6.log
I am info log.
I am warning log.

変数st_handlerにStreamHandlerインスタンス、fl_handlerにFileHandlerインスタンスを格納し、addHandlerメソッドを用いてloggerオブジェクトにそれぞれのハンドラを追加している。
FileHandlerをインスタンス化するときに設定すべき基本的な引数は以下の通りである。

引数名 備考
filename sample.log ログ出力先のファイル名を指定。./logs/sample.logのようなパス指定もここで行う。指定のファイルが存在しなければ、新たに作成されてから出力される。
encoding utf-8 ログがファイルに書き込まれる際の文字コードで、日本語を出力したい場合などはここでutf-8を指定しないと文字化けが発生する。

ハンドラのカスタマイズ

次に、loggerに渡す道具(=ハンドラ)を更にカスタマイズする方法を説明する。
今回の記事で具体的に設定する項目は以下の通り。

  • ハンドラからの最低出力レベル
  • 出力に含める情報と出力フォーマット

コード上での設定方法についてそれぞれ示す。

ハンドラからの最低出力レベル

先程loggerからの最低出力レベルは設定したが、ハンドラからの最低出力レベルも個別に設定できるようになっている。
StreamHandlerとFileHandlerのそれぞれに、最低出力レベルを設定するコードを以下に示す。

sample7.py
import logging
logger = logging.getLogger("ログ太郎")
logger.setLevel(logging.DEBUG)

st_handler = logging.StreamHandler()
# StreamHandlerの最低出力レベルをDEBUGに設定
st_handler.setLevel(logging.DEBUG)

fl_handler = logging.FileHandler(filename="sample7.log", encoding="utf-8")
# FileHandlerの最低出力レベルをWARNINGに設定
fl_handler.setLevel(logging.WARNING)

logger.addHandler(st_handler)
logger.addHandler(fl_handler)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
# 実行結果
>>> I am info log.
>>> I am warning log.
sample7.log
I am warning log.

このコードでは、StreamHandlerの最低出力レベルをDEBUG、FileHandlerの最低出力レベルをWARNINGに設定している。これは、開発時にターミナルでは全てのログを確認したいが、ファイルに記録しておくのはある程度重大度の高いWARNING以上でよいという場面を想定している。

ここで注意しておきたいのは、logger自身にも最低出力レベルが設定され、道具であるHandlerにもそれぞれ最低出力レベルが設定されるという点だ。
logger自身の最低出力レベルがWARNING以上となっていた場合、そもそもloggerからログが吐き出されないため、Handlerの最低出力レベルをDEBUGに設定したところでWARNING以上しか出力されないことに注意してほしい。

ハンドラからの出力フォーマット

各ハンドラの出力値は、デフォルトではメソッドの引数で渡したメッセージのみである。しかしloggerを用いた出力には、発生日時や発生場所等の追加情報を含めることができる。
loggerからログが出力される際の情報は、logging.LogRecordインスタンスが保持しており、そこから以下の表にある情報が取得可能である。

パラメータ名 説明
name ロガーの名前
asctime タイムスタンプの文字列表現
created タイムスタンプ(秒単位)
levelname ログレベル名(INFO, WARNING, etc.)
levelno ログレベル番号(10, 20, etc.)
message ログメッセージ
module ログ発生モジュール名
filename ログ発生ファイル名
pathname ログ発生ファイルのフルパス
funcName ログ発生関数名
lineno ログ発生行番号
process プロセスID
thread スレッドID
threadName スレッド名
msecs タイムスタンプのミリ秒部分
relativeCreated ロガー生成からの経過時間(ミリ秒)

これらの中から必要なデータを選び、書式化演算子を用いてフォーマット化する。
今回はlevelnameasctimefilenamelinenomessageを用いて以下のようなフォーマットを作成する。

sample8.py
format = "%(levelname)-9s  %(asctime)s [%(filename)s:%(lineno)d] %(message)s"
書式化演算子とは

書式化演算子%は、Pythonで文字列を書式設定するための古い方法で、C言語のprintfスタイルに似てた表現である。文字列内で%記号の後に特定の書式指定子を配置し、その後ろに%演算子と値のタプルまたは辞書を提供することで、文字列の編集ができる。

書式指定子の例

書式指定子 説明
's' 文字列
'd' 符号付き10進整数
'f' 浮動小数点数

実際の使用例

tips1.py
name = "Dencyu"
age = 21
message = "Thank you for reading my article!"

# タプル用編集フォーマット
tuple_format = "I'm %s. I'm %d years old. %s"
# 辞書用編集フォーマット
dict_format = "I'm %(name)s. I'm %(age)d years old. %(message)s"

print(tuple_format % (name, age, message))
print(dict_format % {"name":name, "age":age, "message":message})
# 実行結果
>>> I'm Dencyu. I'm 21 years old. Thank you for reading my article!
>>> I'm Dencyu. I'm 21 years old. Thank you for reading my article!

> 組み込み型 printf形式でのbytesの書式化

ハンドラへのフォーマット設定

先で作成したフォーマット通りに出力させるには、loggerに道具(ハンドラ)を渡す前に、ハンドラ自体にフォーマットを設定しておく必要がある。
以下ではそのハンドラへのフォーマット設定をコードで示す。

sample9.py
import logging
logger = logging.getLogger("ログ太郎")
logger.setLevel(logging.DEBUG)

format = "%(levelname)-9s  %(asctime)s [%(filename)s:%(lineno)d] %(message)s"

st_handler = logging.StreamHandler()
st_handler.setLevel(logging.DEBUG)
# StreamHandlerによる出力フォーマットを先で定義した'format'に設定
st_handler.setFormatter(logging.Formatter(format))

fl_handler = logging.FileHandler(filename="sample9.log", encoding="utf-8")
fl_handler.setLevel(logging.WARNING)
# FileHandlerによる出力フォーマットを先で定義した'format'に設定
fl_handler.setFormatter(logging.Formatter(format))

logger.addHandler(st_handler)
logger.addHandler(fl_handler)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
# 実行結果
>>> INFO       2023-03-26 17:12:57,297 [sample9.py:20] I am info log.
>>> WARNING    2023-03-26 17:12:57,298 [sample9.py:21] I am warning log.
sample9.log
WARNING    2023-03-26 17:12:57,298 [sample9.py:21] I am warning log.

ハンドラに対してフォーマットを設定するには、各HandlerインスタンスのsetFormatterメソッドに、loggingモジュールのFormatterクラスを渡して実行する。さらにそのFormatterクラスには、先ほど書式化演算子を用いて定義したフォーマットの文字列を渡すことで、ハンドラからの出力に任意のフォーマットが適用される。

> logging ---Python用ロギング機能 フォーマッタオブジェクト

str.format()とは

str.format()は、Pythonの文字列メソッドで、文字列内のプレースホルダに値を埋め込むために使用される。このメソッドを使用すると、文字列を効率的かつ柔軟に構築することが可能となる

str.format()の使用例

tips2-1.py
formatted_str = "My name is {}. I'm {} years old.".format("Dencyu", 21)
print(formatted_str)
terminal
# 実行結果
>>> My name is Dencyu. I'm 21 years old.

また、str.format()は以下のような高度な書式設定も可能である。

  1. 位置引数: プレースホルダ内に引数の位置を明示的に指定できる
tips2-2.py
formatted_str = "I'm {1} years old. My name is {0}.".format("Dencyu", 21)
print(formatted_str)
terminal
>>> I'm 21 years old. My name is Dencyu.
  1. キーワード引数: プレースホルダ内にキーワードを指定し、対応する値を渡すことができる
tips2-3.py
formatted_str = "My name is {n}. I'm {a} years old.".format(n="Dencyu", a=21)
print(formatted_str)
terminal
>>> My name is Dencyu. I'm 21 years old.
  1. 書式指定: 数値や文字列の表示形式を制御するために、書式指定子を使用できる
tips2-4.py
formatted_str = "PI rounded to 3 decimal places: {:.3f}".format(3.1415927535)
print(formatted_str)
terminal
>>> PI rounded to 3 decimal places: 3.142

> 7.入力と出力 7.1.2. 文字列の format() メソッド

str.format()を用いたフォーマット設定方法

str.format()を用いたハンドラへのフォーマット設定は、loggingモジュール内のFormatterクラスにstyle="{"を設定することで実現可能である。
以下に、先ほどの書式化演算子を用いた例と同等の処理をstr.format()によって行うコードを示す。

tips3.py
import logging
logger = logging.getLogger("ログ太郎")
logger.setLevel(logging.DEBUG)

# str.format()用のプレースホルダーによるフォーマット
format = "{levelname}  {asctime} [{filename}:{lineno}] {message}"

st_handler = logging.StreamHandler()
st_handler.setLevel(logging.DEBUG)
# Formatterの引数styleに"{"を指定
st_handler.setFormatter(logging.Formatter(format, style="{"))

fl_handler = logging.FileHandler(filename="tips3.log", encoding="utf-8")
fl_handler.setLevel(logging.WARNING)
# Formatterの引数styleに"{"を指定
fl_handler.setFormatter(logging.Formatter(format, style="{"))

logger.addHandler(st_handler)
logger.addHandler(fl_handler)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
# 実行結果
>>> INFO       2023-03-26 17:12:57,297 [tips3.py:21] I am info log.
>>> WARNING    2023-03-26 17:12:57,298 [tips3.py:22] I am warning log.
tips3.log
WARNING    2023-03-26 17:12:57,298 [tips3.py:22] I am warning log.
string.Templateとは

Pythonのstring.Templateクラスは、文字列内のプレースホルダに値を埋め込むためのもう一つの方法で、str.format()と同様に、文字列を効率的かつ柔軟に構築することが可能である。
string.Templateクラスの特徴は以下のとおりである

  • '$'記号を使ったシンプルなプレースホルダーが使用できる
  • string.Templateはプレースホルダの名前解決に辞書を使用するため、外部からの不正な属性アクセスやメソッド呼び出しを防ぐことができる
  • '$'記号自体を文字列に含めたい場合、$$と記述することができる
  • str.format()に比べて書式設定の機能が限定的であるため、複雑な書式設定が必要な場合には不適切である

string.Templateの使用例

string.Templateクラスの使用手順は以下の通り。

  1. stringモジュールのインポート
  2. プレースホルダを含む文字列を定義し、string.Templateクラスのインスタンスを作成
  3. substitute()またはsafe_substitute()メソッドを使用し、プレースホルダに値を埋め込む

以下にコードを示す。

tips4.py
import string

# フォーマット用テンプレート作成
template_str = "My name is $name. I'm $age years old."
template = string.Template(template_str)

# 値挿入用の辞書作成
values = {"name": "Dencyu", "age": 21}

# 値を埋め込んだ文字列の作成
formatted_str = template.substitute(values)
print(formatted_str)
terminal
>>> My name is Dencyu. I'm 21 years old.

> string --- 一般的な文字列操作 テンプレート文字列

string.Templateを用いたフォーマット設定方法

string.Templateを用いたハンドラへのフォーマット設定は、loggingモジュール内のFormatterクラスにstyle="$"を設定することで実現可能である。
以下に、先ほどの書式化演算子を用いた例と同等の処理をstring.Templateによって行うコードを示す。

tips5.py
import logging
logger = logging.getLogger("ログ太郎")
logger.setLevel(logging.DEBUG)

# string.Template用のプレースホルダーによるフォーマット
format = "$levelname  $asctime [$filename:$lineno] $message"

st_handler = logging.StreamHandler()
st_handler.setLevel(logging.DEBUG)
# Formatterの引数styleに"$"を指定
st_handler.setFormatter(logging.Formatter(format, style="$"))

fl_handler = logging.FileHandler(filename="tips5log", encoding="utf-8")
fl_handler.setLevel(logging.WARNING)
# Formatterの引数styleに"$"を指定
fl_handler.setFormatter(logging.Formatter(format, style="$"))

logger.addHandler(st_handler)
logger.addHandler(fl_handler)

logger.info("I am info log.")
logger.warning("I am warning log.")
terminal
# 実行結果
>>> INFO       2023-03-26 17:12:57,297 [tips5.py:21] I am info log.
>>> WARNING    2023-03-26 17:12:57,298 [tips5.py:22] I am warning log.
tips5.log
WARNING    2023-03-26 17:12:57,298 [tips5.py:22] I am warning log.
なぜloggerのフォーマッタには書式化演算子が用いられるのか

上のTipsで、書式化演算子以外のフォーマット設定方法を2つ示したが、公式で使用されているのは文字列処理としては古い書式化演算子を用いた方法である。
書式化演算子を用いた場合と、str.format()を用いた場合、そしてstring.Templateクラスを用いた場合に何の違いが生まれるのかについて、以下で言及する。

書式化演算子とstr.format()

書式化演算子とstr.format()の違いとして、書式化演算子を用いた場合に遅延評価が行われるという点が挙げられる。遅延評価とは、ログレコードが実際に出力されるまで、文字列の書式設定を遅らせることができる性質である。
例えばDEBUGレベルのログメッセージがあり、loggerの最低出力レベルがINFOに設定されていた場合、書式化演算子を使用するとデバッグメッセージの書式設定が実行されず、リソースが節約される。一方でstr.format()を用いた場合、最低出力レベル以下の出力されないログメッセージに対しても書式設定が実行される。

書式化演算子とstring.Template

遅延評価は書式化演算子とstring.Templateの両方において行われるため、この点の差異はほとんどない。また一般的にstring.Templateを使用したケースは、書式化演算子やstr.format()よりも実行速度が速いと言われている。ただしその素早い実行速度は、string.Templateの機能のシンプルさに起因するものであるため、書式化演算子やstr.format()のように複雑で高度な書式設定を必要とする場合には使用できないという一面もある。

loggerによるカスタムログの出力手順のまとめ

以下に、今回の記事で示したloggerオブジェクトによるカスタム済みのログを出力するための手順をまとめる。

  1. loggingモジュールのインポート
  2. loggerオブジェクトを取得
  3. loggerオブジェクトの最低出力レベルを設定
  4. 出力用フォーマット文字列を定義
  5. 必要なハンドラをインスタンス化
  6. ハンドラからの最低出力レベルをそれぞれ設定
  7. ハンドラにフォーマットを設定
  8. loggerにハンドラを追加
  9. loggerオブジェクトのメソッドを使用してログ出力

ログ出力コードを設置してみたものの、上手くログが出力されない場合などは今一度上の手順を確認していただきたい。

応用編

ここからは実際の運用上必要な設定項目や、更なるカスタマイズ性を求める読者用に、応用編と題していくつかのトピックについて解説していこうと思う。
興味のある方は読み進めてほしい。

ファイル出力に関する実運用上必要な設定

ここまでで、基本的なログ出力設定はできるようになっていると思うが、特にファイルへのログ出力は、その性質上時間経過と共に容量が増え続けるものである。
そこで実際の運用時には、ログファイルの循環についての設定をしておく必要がある。
ログファイルの循環とは、出力先のファイルを容量もしくは経過時間によって新しいものと切り替える設定のことである。
ログファイルの循環は、RotatingFileHandlerTimedRotatingFileHandlerをインスタンス化し、loggerに追加することで設定できる。
以下にRotatingFileHandlerやTimedRotatingFileHandlerについて簡単に示しておく。

RotatingFileHandlerクラス

RotatingFileHandlerを使用すると、ログイベントが発生した際に、指定されたファイルにログメッセージが出力される。また、ログファイルが指定されたサイズに達すると、ローテーションが行われ、新しいファイルにログ出力が切り替わるようになる。
以下にRotatingFileHandlerの設定項目(インスタンス化時の引数)を一覧で示しておく

引数 説明
filename str ログを出力するファイル名を指定する。ファイルへのパスも含めることができる。例: "logs/myapp.log"
mode str(optional) ファイルオープンモードを指定する。デフォルトは'a' (追記モード) 。他のオプションとして 'w' (書き込みモード) などがある。
maxBytes int(optional) ログファイルがこのサイズに達した場合にローテーションを行う。デフォルトは 0で、この場合ローテーションはサイズに基づいては行われない。
backupCount int(optional) 保持するバックアップファイルの最大数を指定する。デフォルトは 0 で、この場合古いバックアップファイルは削除されない
encoding str(optional) ファイルのエンコーディングを指定する。デフォルトは None で、システムのデフォルトエンコーディングが使用される。
delay bool(optional) ファイルオープンの遅延を指定する。True の場合、emit()が呼び出されるまでファイルオープンを遅延させる。デフォルトは False 。
errors str(optional) エンコードやデコードのエラー処理方法を指定する。デフォルトは 'strict' 。他のオプションとして 'ignore' や 'replace' などがある。

TimedRotatingFileHandlerクラス

TimedRotatingFileHandlerを使用すると、ログイベントが発生した際に、指定されたファイルにログメッセージが出力される。また、指定された時間や間隔に基づいてログファイルのローテーションが行われ、新しいファイルにログ出力が切り替わるようになる。
以下にTimedRotatingFileHandlerの設定項目(インスタンス化時の引数)を一覧で示しておく

引数 説明
filename str ログを出力するファイル名を指定する。ファイルへのパスも含めることができる。例: "logs/myapp.log"
when str(optional) ローテーションの基準となる時間を指定する。デフォルトは 'H' (1時間ごと)。他に 'S' (秒), 'M' (分), 'D' (日), 'W0'-'W6' (曜日), 'midnight' (真夜中) などが利用できる。
interval int(optional) ローテーションの間隔を指定する。デフォルトは 1 で、when で指定された単位での間隔が適用される。
backupCount int(optional) 保持するバックアップファイルの最大数を指定する。デフォルトは 0 で、古いバックアップファイルは削除されない
encoding str(optional) ファイルのエンコーディングを指定する。デフォルトは None で、システムのデフォルトエンコーディングが使用される。
delay bool(optional) ファイルオープンの遅延を指定する。True の場合、emit()が呼び出されるまでファイルオープンを遅延させる。デフォルトは False 。
errors str(optional) エンコードやデコードのエラー処理方法を指定する。デフォルトは 'strict' 。他のオプションとして 'ignore' や 'replace' などがある。
utc bool(optional) ローテーション時刻をUTC基準にするかどうかを指定する。デフォルトは False で、ローカル時刻が使用される。True の場合、UTC時刻が使用される。

loggerへの更なるカスタマイズ

printとloggingの違いで示したように、ログの出力先をメール送信にしたい、またはHTTP通信によるリクエストにしたい場合がある。
ここまで読み進めてくれた読者はお気づきかもしれないが、その機能に応じたハンドラを設定し、loggerオブジェクトに追加すれば実現可能である。
以下にSMTPHandlerとHTTPHandlerについて簡単に示しておく。

SMTPHandlerクラス

loggerのログ出力メソッドが実行されたとき、指定のメールアドレスにメールを送信する機能を追加するためのハンドラである。
以下にSMTPHandlerの設定項目(インスタンス化時の引数)を一覧で示しておく

引数 説明
mailhost tuple or str メールサーバーのホスト名またはIPアドレスとポート番号を指定する。例: ("smtp.example.com", 587)。ポート番号を省略した場合、デフォルトのSMTPポート(25)が使用される。
fromaddr str 送信元のメールアドレスを指定する。
toaddrs list or str 送信先のメールアドレスを指定する。複数のアドレスがある場合は、リストで指定可能。
subject str メールの件名を指定する。
credentials tuple(optional) メールサーバーへの認証情報を指定する。例: ("username", "password")。認証が不要な場合は省略可能。
secure tuple(optional) TLS接続に関する設定を指定する。secureには、STARTTLSで使用するキーワード引数が含まれるタプルを渡す。例: (), {"keyfile": "key.pem", "certfile": "cert.pem"}。TLS接続が不要な場合は省略可能。
timeout float(optional) サーバーへの接続タイムアウトを秒単位で指定する。デフォルトは1.0。

HTTPHandler

loggerのログ出力メソッドが実行されたとき、指定のHTTPサーバーにリクエストを送信する機能を追加するためのハンドラである。
以下にHTTPHandlerの設定項目(インスタンス化時の引数)を一覧で示しておく

引数 説明
host str ログを送信するHTTPサーバーのホスト名またはIPアドレスを指定する。例: "example.com"
url str ログを送信するHTTPサーバーのURLを指定する。例: "/log-handler"
method str(optional) リクエストメソッドを指定する。デフォルトは "GET"だが、 "POST"も指定可能。
secure bool(optional) HTTPS接続を使用するかどうかを指定する。デフォルトはFalseで、HTTPS接続を使用する場合はTrueを指定する。
credentials tuple(optional) HTTPサーバーへの認証情報を指定する。例: ("username", "password")。認証が不要な場合は省略可能。
context ssl.SSLContext(optional) SSLコンテキストを指定する。デフォルトはNoneで、指定された場合、接続にそのコンテキストが使用される。secure=Trueの場合に有効。

参考にしたページ

Discussion