適当おじさんの適当ブログ

技術のことやゲーム開発のことやゲームのことなど自由に雑多に書き連ねます

いまさらながら Flask についてまとめる 〜Logging〜

はじめに

いまさらながら Flask について整理していきます。「Flaskとかいうやつを使って、試しにアプリ開発にトライしてみたい」くらいの感覚の人を対象にしています。

Flaskのバージョンは 0.12.2 です。Flask 1.0からは挙動が変わっており、このページに記載されていることはほとんど変更されているので注意してください。1.0.2時点の情報を以下に整理しなおしました。

www.subarunari.com

この記事では、Logging について紹介していきます。その他のFlaskまとめシリーズはこちらから

Logging

Flaskのloggerを使うことで、Python標準のloggingLoggerを取得できます。パッケージ名を名前に持つLoggerが取得されます。

# log_test.py
from flask import Flask                                                         
                                                                                  
app = Flask(__name__)                                                                                                                          
                                                                            
@app.route('/')                                                                 
def index():                                                                    
    app.logger.debug('debug')                                                   
    app.logger.info('info')                                                     
    app.logger.warn('warn')                                                     
    app.logger.error('error')                                                   
    app.logger.critical('critical')                                                                                                                         
    return "logging"                                                            
                                                                                                                                                    
if __name__ == '__main__':                                                      
    app.run(debug=True)              

上記アプリケーションにアクセスすると、コンソールに各種ログが出力されていることが確認できると思います。

デフォルトで登録されているHandler

app.loggerには、DebugHandlerProductionHandler が登録されています。debug=True(デバッグモード)で実行した場合はDebugHandlerで、そうでない場合はProductionHandlerでログが出力されます。それぞれのHandlerは異なるログレベルとログフォーマットが設定されています。

つまり、デバッグモードで実行するか否かでログレベルとログフォーマットが変化します。ログレベルについてはこちらを参照ください。

デバッグモードで実行した場合

DEBUG以上 のログレベルのログが出力されます。また、このときのログフォーマットは以下になります。

--------------------------------------------------------------------------------
%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:
%(message)s
--------------------------------------------------------------------------------
デバッグモードでない場合

ERROR以上 のログレベルのログが出力されます。ログのフォーマットは以下になります。

[%(asctime)s] %(levelname)s in %(module)s: %(message)s

ログの出力先を変更する

Python標準のLoggerは、Handler によって出力先を変更します。そして先述した通り、app.loggerで得られるLoggerはPython標準のものです。つまり、Flaskアプリケーションでも同様に、LoggerにHandlerを追加/削除することでログの出力先を変更できます。

Pythonには様々なHandlerが標準で用意されています。これらのHandlerを追加すれば良いです。ちなみに、コンソールに出力しているHandlerは StreamHandler です。

RotatingFileHandler

RotatingFileHandler は、ログをファイルに出力し、かつ、サイズに応じてローテーションしてくれる便利なHandlerです。これを例にFlaskのLoggerにHandlerを追加します。

import logging                                                                  
import logging.handlers  
from flask import Flask                                                      
                                                                                  
app = Flask(__name__)     

# Add RotatingFileHandler to Flask Logger
handler = logging.handlers.RotatingFileHandler("test.log", "a+", maxBytes=3000, backupCount=5)
handler.setLevel(logging.INFO) 
handler.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s'))
app.logger.addHandler(handler)

@app.route('/')                                                                 
def index():                                                                    
    app.logger.debug('debug')                                                   
    app.logger.info('info')                                                     
    app.logger.warn('warn')                                                     
    app.logger.error('error')                                                   
    app.logger.critical('critical')                                                                                                                         
    return "logging"                                                            
                                                                                                                                                    
if __name__ == '__main__':                                                      
    app.run(debug=True)                                 

同様にアプリケーションにアクセスすると、test.logが生成され、ログメッセージが書かれていることが確認できます。 このようにして、Python標準のLoggerと同じようにHandlerを追加できます。

Python標準のLoggerのみを使いたい場合

FlaskのLoggerを使わず、それらを無効にしたい場合もあるかもしれません。そのときの設定方法です。アプリケーションのできるだけ早い段階で無効化処理をしておかないと、思わぬところでログが出力されてしまう可能性があります。

import logging                                                                  
import logging.handlers  
from flask import Flask                                                         
                                                                                  
app = Flask(__name__)   
# FlaskのLoggerを無効化する
app.logger.disabled = True  
# werkzeugのLoggerを無効化する
werkzeug_logger = logging.getLogger('werkzeug')   
werkzeug_logger.disabled = True  

また、FlaskのLoggerにデフォルトで登録されているHandlerを削除したい場合は以下です。

app.logger.handlers.clear()

ただ、すべてのHandlerを削除するくらいなら、上記の方法で無効化してPython標準のLoggerにHandlerを登録したほうがわかりやすくて良い気がします。