kumilog.net

データ分析やプログラミングの話などを書いています。

Pythonのログ出力にlogzeroを使う

Python その2 Advent Calendar 2018 10日目の記事です。

はじめに

Pythonでログ出力する際に何を使っていますか、printでしょうか。それともloggingでしょうか。ロギングは奥が深いようで、以下の記事ではloggingの使い方を詳説されています。

標準ライブラリのloggingでも良いのですが、今回はより簡単にログ出力が可能なlogzeroというライブラリを紹介したいと思います。

インストール

インストールは他のライブラリと同じくpipでできます。

$ pip install logzero

使い方

基本

基本は、以下のように使うことができます。

from logzero import logger

logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')

色付きで出力されます。

f:id:xkumiyu:20181208171138p:plain

ログレベルの設定

ログレベルを設定すると必要に応じて出力を制限することができます。

import logzero

# INFO以上(INFO, WARNING, ERROR)を表示
logzero.loglevel(20)

# ERRORのみ表示
logzero.loglevel(40)

指定する値はloggingと同じです。なので、以下のようにも書くことができます。

import logging

# INFO以上を表示
logzero.loglevel(logging.INFO)

# ERRORのみ表示
logzero.loglevel(logging.ERROR)

デフォルトは10logging.DEBUG)ですべて表示します。

またログレベルの名前と値の対応は以下の表のとおりです。

ログレベル
DEBUG 10
INFO 20
WARNING 30
ERROR 40

ファイルに出力

ログをファイルに出力するにはlogzero.logfileを使います。

logzero.logfile('sample.log')

標準出力に加えて、ファイルにも出力することができるようになります。

標準出力はいらないという場合は、オプションで切ることもできます。

logzero.logfile('sample.log', disableStderrLogger=True)

ログファイルへの出力のログレベルは、logzero.loglevelで指定したものが使われますが、異なるログレベルをしたいときはオプションで指定することができます。

# 標準出力はINFO以上
logzero.loglevel(20)
# ファイルにはERRORのみ
logzero.logfile('sample.log', loglevel=40)

ログローテーション

ログのローテーションも、logzero.logfileのオプションで簡単に行うことができます。

# 最大1024B=1KBのログファイルを3世代まで
logzero.logfile('sample.log', maxBytes=1024, backupCount=3)

maxBytesでログファイルの最大容量を指定し、超えるとsample.logsample.log.1にリネームされます。

sample.log.1がすでにある場合は、sample.log.1sample.log.2にリネームされ、sample.logsample.log.1にリネームされます。

新たに書き込まれるのは、常にsample.logとなります。

backupCountで何世代まで保存するか指定し、超えると破棄されます。backupCount=3の場合、sample.log.3まで作成されます。

注意点として、ログローテーションを行うためには、maxBytesbackupCountの両方を指定する必要があります。 片方を指定しない場合や0を指定した場合はローテーションは行われません。

フォーマット変更

標準では

[D 181208 16:06:22 main:5] debug
[I 181208 16:06:22 main:6] info
[W 181208 16:06:22 main:7] warning
[E 181208 16:06:22 main:8] error

のようなログが出力されましたが、フォーマットを変更することもできます。

変更するには、logzero.formatterを使い、logging.Formatterで指定します。

formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
logzero.formatter(formatter)

上の例だと、以下のような形式で出力されます。(色は消えました。。)

2018-12-08 16:29:10,652 DEBUG: debug
2018-12-08 16:29:10,652 INFO: info
2018-12-08 16:29:10,652 WARNING: warning
2018-12-08 16:29:10,652 ERROR: error

asctimeなどのlogging.Formatterの形式は以下のドキュメントを参照すると良いです。

16.6. logging — Python 用ロギング機能 — Python 3.6.5 ドキュメント

まとめて設定

logzero.setup_loggerを使うとこれまで紹介してきた設定をまとめて行うことができます。むしろこれだけでいいような気がします。

logger = logzero.setup_logger(
    name='logzero-sample',      # loggerの名前、複数loggerを用意するときに区別できる
    logfile='sample.log',       # ログファイルの格納先
    level=20,                   # 標準出力のログレベル
    formatter=None,             # ログのフォーマット
    maxBytes=1000,              # ログローテーションする際のファイルの最大バイト数
    backupCount=3,              # ログローテーションする際のバックアップ数
    fileLoglevel=40,            # ログファイルのログレベル
    disableStderrLogger=False   # 標準出力するかどうか
    )

おわりに

ログ出力を手軽に行うことができるライブラリlogzeroを紹介しました。

これまで、ちょっとしたスクリプトだとprintで出力していたものも、これを使えば簡単に書けそうなので、積極的に使っていこうかなと思います。