読者です 読者をやめる 読者になる 読者になる

ログをとる

Django mod_wsgi

mod_wsgiで開発を行うようになって困るのは、標準の状態ではsys.stdoutへの書き込みがmod_wsgiによって制限されるので、printデバッグが使えなくなってしまうことです。

より正確にいうと、mod_wsgiのWSGIRestrictStdoutディレクティブをOnにすると、printでstdoutに書き込んだ内容がstderr(Apacheのエラーログ)に出力されるのでprintデバッグもできなくはないのですが、print文を使っていると10年後くらいにPython3.0系に移行する際手間がかかるかもしれない*1ので別の手段を使うのが大人の流儀というものでしょう。*2

そんなわけでloggingモジュールを使うわけですが、どこでloggingモジュールの初期設定を行うかという問題が残ります。

一番簡単なのは、myproject.logのようなモジュールを用意して、

# myproject/log.py
import logging

def init_logging():
    root = logging.getLogger()
    # ここにloggingの設定を書く
    root.setLevel(logging.DEBUG)

mod_wsgi起動スクリプトの中に、

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'

from myproject.log import init_logging
init_logging()

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

と書いてしまうことでしょうか。

もう少し高級なやり方は、ロギング用のMiddlewareを用意すること。自分で書かなくても、例えば次の2つなどが利用できます。

開発のデバッグ用のロギングならば、断然後者をおすすめ。なぜなら、ログの内容をブラウザに出力してくれるから。

settings.pyのMIDDLEWARE_CLASSESに、djangologging.middleware.LoggingMiddlewareを追加し、

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'djangologging.middleware.LoggingMiddleware',
)

さらに、ログの出力を許す接続先をINTERAL_IPSに設定。

INTERNAL_IPS = ('127.0.0.1',)

あとは、通常通りloggingモジュールを使って、

from django.shortcuts import render_to_response
from django.template import RequestContext

import logging

def myview(req):
    logging.error("error")
    logging.warning("warning")
    logging.info("info")
    logging.debug("debug")
    ctxt = RequestContext(req)
    return render_to_response('base.html', ctxt)

のようにすれば、このとおり。

djangologging
djangologging posted by (C)perezvon

*1:まあ、2to3を使えばいいわけですが。

*2:Python3.0うんぬんは冗談で、「いたるところでprintするアプリケーションはよいアプリケーションではない」ということが主たる理由なのは皆さん分かっていただけていることと思います。