Pythonのログの仕組み

ややこしかったので、ここにメモしておく。(参考:Logging HOWTO

loggingライブラリでログ出力をなんやかんや制御できる。

loggingライブラリは、ロガー、ハンドラ、フィルタ、フォーマッタという部品からなる。この4つの働きと関係性を把握しないとわけが分からなくなる。

  • ロガーは、アプリケーションコードが直接使うインターフェースを公開します。

  • ハンドラは、(ロガーによって生成された) ログ記録を適切な送信先に送ります。(要は、ログ出力先が画面コンソールか、ファイル書き出しかなどを定義する)

  • フィルタは、どのログ記録を出力するかを決定する、きめ細かい機能を提供します。

  • フォーマッタは、ログ記録が最終的に出力されるレイアウトを指定します。(要は、ログ出力するときのフォーマットなどを定義。例えば日付のyyy-mm-ddなど)

下記の絵がロガー、ハンドラ、フィルタ、フォーマッタの関係が書かれており、イメージしやすい。

Sample ローテートするログファイルを、フォーマット指定して定義

import logging
import logging.handlers

# create logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.handlers.RotatingFileHandler(‘APL.log’, mode=’a’,maxBytes=50, backupCount=5)
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’)

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# ‘application’ code
logger.debug(‘debug message’)
logger.info(‘info message’)
logger.warning(‘warn message’)
logger.error(‘error message’)
logger.critical(‘critical message’)

 

ーーー解説ーーーーーーーーー
import logging
import logging.handlers

# create logger
logger = logging.getLogger(‘example’) ここで定義したexampleという名前が、後述のフォーマッタで%(name)sと定義するとログに出力されるため、ロガー名だけで、どこでイベントのログが取られたか、直感的に明らかになる。これは、Logging HOWTOにも以下のように書かれている。
 

ガーに名前をつけるときの良い習慣は、ロギングを使う各モジュールに、以下のように名付けられた、モジュールレベルロガーを使うことです:

logger.setLevel(logging.DEBUG) —(1)
(1) ロガーが扱うログメッセージの最も低い深刻度を指定

# create console handler and set level to debug
ch = logging.handlers.RotatingFileHandler(‘APL.log’, mode=’a’,maxBytes=50, backupCount=5)-–(2)   ログファイルローテートするタイプのハンドラ。APL.logというログファイルが作成され、ファイルサイズが50バイトを超えると自動ローテートされ、ローテートのファイル数は最大5.5を超えると古いファイルから上書きされる。
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’)--(3)  書き出し文字列のフォーマット指定

# add formatter to ch
ch.setFormatter(formatter) フォーマットをハンドラにセット

# add ch to logger
logger.addHandler(ch) ハンドラをロガーにセット

# ‘application’ code
logger.debug(‘debug message’) これらのログ出力がファイルに書き出される
logger.info(‘info message’)
logger.warning(‘warn message’)
logger.error(‘error message’)
logger.critical(‘critical message’)

venv使い方

venvはPython3.3以降で標準に入っている仮想環境の作成、管理ができるモジュール。1つのPCやサーバ内にて、アプリごとに違うバージョンのpthhonやライブラリを利用する可能性がある場合は、それぞれ仮想環境を用意して開発運用するのが便利。

venvで仮想環境を構築

$python3 -m venv [ env name ]

仮想環境に入る

$. [env name]/Scripts/activate

※Windows環境でのactivate方法

仮想環境の終了

$deactivate

wfastcgi-enable.exeを実行すると”failed to create process”

IISでPythonアプリを動かすため、wfastcgiをpipでインストールし、wfastcgi-enable.exeをたたいたときに

failed to create process  のエラー発生。

いろいろ調べた所、wfastcgi-enable-script.pyのほうの一行目を
#!c:\program files (x86)\python35\python.exe

#!”c:\program files (x86)\python35\python.exe”  に変更した所、うまくいった。pythonでは、program files のようのフォルダ名のなかに空白が入っていると、今回のようにうまくいかないモジュールがある模様。Pythonは無難にC:\pyhon3.6.1のように空白文字を入れないようなディレクトリパスでインストしておくほうがよい。

Python の属性

Python では、インスタンス変数やクラス変数、メソッドのことを「属性 (attribute) 」といいます。属性は名前で管理されていて、同じ名前のインスタンス変数とメソッドを同時に使うことはできません。インスタンス変数の方が優先されるため、メソッドを呼び出すことができなくなります。インスタンス変数はクラス変数やメソッドよりも優先されることに注意してください。

formにBootstrapのスタイルを適用

 

Bootstrapのフォームスタイルを適用するには、class属性にform-controlと定義する必要がある。Djangoのフォームに、このform-controlを仕込むには、
widget.attrsを使い、下記のように定義する。

例えばforms.pyにて下記のように定義

すると、HTMLタグに

 
とclass属性がちゃんと定義される。

python unittest

unittestには
unittest.TestCaseクラスを継承したクラスにテストメソッドを記述
テストメソッドはtest_*で始める
というルール。これさえ守ればコマンドラインからテストを実行することが可能。

unittest用のディレクトリ構成
.
├─sample.py
└─tests
├─__init__.py
└─test_sample.py

Django:フィールドのアップデートのやりかた

Domainテーブルにdomain_id列と、data_alert_flag列があるとする、
特定のdomain_idを保有している行のみを抽出し、その行のdata_alert_flag列の値を更新するには、

パターン1:

※.save()を実行する必要なし。.updateを実行すると保存される。

パターン2:

 

Model:choiceを定義するときの設定間違い

RANK_CHOICES = (
(1, ‘Principal’),
(2, ‘Vice’),
)

だとデータ登録時に下記のエラーが発生する。

return int(value)
ValueError: invalid literal for int() with base 10: ”

ただしくは、下記のように二要素のタプルにてクォートで囲む。

RANK_CHOICES = (
(‘1’, ‘Principal’),
(‘2’, ‘Vice’),
)

admin_rank = models.CharField(max_length=50,choices=RANK_CHOICES, blank=False,default=”)