15.8. "logging.config" --- ロギングの環境設定
*********************************************


Important
^^^^^^^^^

このページには、リファレンス情報だけが含まれています。チュートリアルは
、以下のページを参照してください

* 基本チュートリアル

* 上級チュートリアル

* ロギングクックブック

**ソースコード:** Lib/logging/config.py

======================================================================

この節は、logging モジュールを設定するための API を解説します。


15.8.1. 環境設定のための関数
============================

以下の関数は logging モジュールの環境設定をします。これらの関数は、
"logging.config" にあります。これらの関数の使用はオプションです ---
"logging" モジュールはこれらの関数を使うか、 ("logging" 自体で定義され
ている) 主要な API を呼び出し、 "logging" か "logging.handlers" で宣言
されているハンドラを定義することで設定できます。

logging.config.dictConfig(config)

      辞書からロギング環境設定を取得します。この辞書の内容は、以下の
      環境設定辞書スキーマ で記述されています。

      環境設定中にエラーに遭遇すると、この関数は適宜メッセージを記述し
      つつ "ValueError", "TypeError", "AttributeError" または
      "ImportError" を送出します。例外を送出する条件を (不完全かもしれ
      ませんが) 以下に列挙します:

      * 文字列でなかったり、実際のロギングレベルと関係ない文字列であ
        っ たりする "level"。

      * ブール値でない "propagate" の値。

      * 対応する行き先を持たない id。

      * インクリメンタルな呼び出しの中で見つかった存在しないハンドラ
        id。

      * 無効なロガー名。

      * 内部や外部のオブジェクトに関わる不可能性。

      解析は "DictConfigurator" クラスによって行われます。このクラスの
      コンストラクタは環境設定に使われる辞書に渡され、このクラスは
      "configure()" メソッドを持ちます。 "logging.config" モジュールは
      、呼び出し可能属性 "dictConfigClass" を持ち、これはまず
      "DictConfigurator" に設定されます。 "dictConfigClass" の値は適切
      な独自の実装で置き換えられます。

      "dictConfig()" は "dictConfigClass" を、指定された辞書を渡して呼
      び出し、それから返されたオブジェクトの "configure()" メソッドを
      呼び出して、環境設定を作用させます:

         def dictConfig(config):
             dictConfigClass(config).configure()

      例えば、 "DictConfigurator" のサブクラスは、自身の "__init__()"
      で "DictConfigurator.__init__()" を呼び出し、それから続く
      "configure()" の呼び出しに使えるカスタムの接頭辞を設定できます。
      "dictConfigClass" は、この新しいサブクラスに束縛され、そして
      "dictConfig()" はちょうどデフォルトの、カスタマイズされていない
      状態のように呼び出せます。

   バージョン 2.7 で追加.

logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)

   ログ記録の環境設定を "configparser" 形式のファイル *fname* から読み
   出します。そのファイルの形式は 環境設定ファイルの書式 で記述されて
   いるとおりにしなければなりません。この関数はアプリケーションから何
   度も呼び出すことができ、これによって、 (設定を選択し、選択された設
   定を読み出す機構をデベロッパが提供していれば) 複数の準備済みの設定
   からエンドユーザが選択するようにできます。

   パラメータ:
      * **defaults** -- ConfigParser に渡されるデフォルト値をこの引
        数 で指定することができます。

      * **disable_existing_loggers** -- "False" が指定された場合は、
        こ の呼び出しが行われたときに存在するロガーは有効のまま残され
        ます 。後方互換性のあるやり方で古い振る舞いを保つので、デフォ
        ルト値 は "True" になっています。そのような振る舞いでは、既存
        のロガー またはそれらのロガーの先祖がロギング設定の中で明示的
        に名付けら れていない限り、既存のロガーを無効にします。

   バージョン 2.6 で変更: "disable_existing_loggers" キーワード引数が
   追加されました。以前は、既存のロガーは *必ず* 無効にされていました
   。

logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT)

   指定されたポートでソケットサーバを起動し、新しい設定を待ち受けます
   。ポートが指定されなかった場合は、モジュールのデフォルトの
   "DEFAULT_LOGGING_CONFIG_PORT" が使用されます。ロギング設定は
   "fileConfig()" で処理できるファイルとして送信されます。 "Thread" イ
   ンスタンスを返し、このインスタンスの "start()" を呼び出してサーバを
   起動し、適切なところで "join()" を呼び出すことができます。サーバを
   停止するには、 "stopListening()" を呼び出します。

   ソケットに設定を送るには、まず設定ファイルを読み、それを
   "struct.pack('>L', n)" を使って長さ 4 バイトのバイナリにパックした
   ものを前に付けたバイト列としてソケットに送ります。

   注釈: 設定の部分が "eval()" を通して渡されるので、この関数の使用
     はユー ザに対してセキュリティリスクを公開してしまうかもしれません
     。この 関数は単に "localhost" 上のソケットに接続してリモートマシ
     ンからは 接続を受け付けませんが、 "listen()" を呼んだプロセスのア
     カウント で信頼されていないコードが実行されるシナリオが存在します
     。特に、 "listen()" を呼んだプロセスがユーザがお互いを信頼するこ
     とができな いマルチユーザのマシン上で実行される場合、悪意のあるユ
     ーザは、犠 牲者のユーザのプロセスで本質的に任意のコードを実行する
     ように細工 することができます。単に犠牲者の "listen()" ソケットに
     接続して、 犠牲者のプロセスで実行したいコードを実行するような設定
     を送るだけ です。これは、特にデフォルトポートが使用されている場合
     に行うのが より簡単ですが、異なるポートが使用されていたとしてもそ
     れほど難し くありません)。

logging.config.stopListening()

   "listen()" を呼び出して作成された、待ち受け中のサーバを停止します。
   通常 "listen()" の戻り値に対して "join()" が呼ばれる前に呼び出しま
   す。


15.8.2. 環境設定辞書スキーマ
============================

ロギング設定を記述するには、生成するさまざまなオブジェクトと、それらの
つながりを列挙しなければなりません。例えば、 'console' という名前のハ
ンドラを生成し、'startup' という名前のロガーがメッセージを 'console'
ハンドラに送るというようなことを記述します。これらのオブジェクトは、
"logging" モジュールによって提供されるものに限らず、独自のフォーマッタ
やハンドラクラスを書くことも出来ます。このクラスへのパラメータは、
"sys.stderr" のような外部オブジェクトを必要とすることもあります。これ
らのオブジェクトとつながりを記述する構文は、以下の オブジェクトの接続
で定義されています。


15.8.2.1. 辞書スキーマの詳細
----------------------------

"dictConfig()" に渡される辞書は、以下のキーを含んでいなければなりませ
ん:

* *version* - スキーマのバージョンを表す整数値に設定されます。現在有
  効 な値は 1 だけですが、このキーがあることで、このスキーマは後方互換
  性 を保ちながら発展できます。

その他すべてのキーは省略可能ですが、与えられたなら以下に記述するように
解釈されます。以下のすべての場合において、 '環境設定辞書' と記載されて
いる所では、その辞書に特殊な "'()'" キーがあるかを調べることで、カスタ
ムのインスタント化が必要であるか判断されます。その場合は、以下の ユー
ザ定義オブジェクト で記述されている機構がインスタンス生成に使われます
。そうでなければ、インスタンス化するべきものを決定するのにコンテキスト
が使われます。

* *formatters* - 対応する値は辞書で、そのそれぞれのキーがフォーマッ
  タ id になり、それぞれの値が対応する "Formatter" インスタンスをどの
  よう に環境設定するかを記述する辞書になります。

  環境設定辞書から、 (デフォルトが "None" の) キー "format" と
  "datefmt" を検索し、それらが "Formatter" インスタンスを構成するのに
  使われます。

* *filters* - 対応する値は辞書で、そのそれぞれのキーがフィルタ id に
  な り、それぞれの値が対応する Filter インスタンスをどのように環境設
  定す るかを記述する辞書になります。

  環境設定辞書は、(デフォルトが空文字列の) キー "name" を検索され、そ
  れらが "logging.Filter" インスタンスを構成するのに使われます。

* *handlers* - 対応する値は辞書で、そのそれぞれのキーがハンドラ id
  に なり、それぞれの値が対応する Handler インスタンスをどのように環境
  設 定するかを記述する辞書になります。

  環境設定辞書は、以下のキーを検索されます:

  * "class" (必須)。これはハンドラクラスの完全に修飾された名前です。

  * "level" (任意)。ハンドラのレベルです。

  * "formatter" (任意)。このハンドラへのフォーマッタの id です。

  * "filters" (任意)。このハンドラへのフィルタの id のリストです。

  その他の *すべての* キーは、ハンドラのコンストラクタにキーワード引数
  として渡されます。例えば、以下のコード片が与えられたとすると:

     handlers:
       console:
         class : logging.StreamHandler
         formatter: brief
         level   : INFO
         filters: [allow_foo]
         stream  : ext://sys.stdout
       file:
         class : logging.handlers.RotatingFileHandler
         formatter: precise
         filename: logconfig.log
         maxBytes: 1024
         backupCount: 3

  id が "console" であるハンドラが、 "sys.stdout" を根底のストリームに
  して、 "logging.StreamHandler" としてインスタンス化されます。id が
  "file" であるハンドラが、 "filename='logconfig.log', maxBytes=1024,
  backupCount=3" をキーワード引数にして、
  "logging.handlers.RotatingFileHandler" としてインスタンス化されます
  。

* *loggers* - 対応する値は辞書で、そのそれぞれのキーがロガー名になり
  、 それぞれの値が対応する Logger インスタンスをどのように環境設定す
  るか を記述する辞書になります。

  環境設定辞書は、以下のキーを検索されます:

  * "level" (任意)。ロガーのレベルです。

  * "propagate" (任意)。ロガーの伝播の設定です。

  * "filters" (任意)。このロガーへのフィルタの id のリストです。

  * "handlers" (任意)。このロガーへのハンドラの id のリストです。

  指定されたロガーは、指定されたレベル、伝播、ハンドラに従って環境設定
  されます。

* *root* - これは、ルートロガーへの設定になります。この環境設定の進
  行 は、"propagate" 設定が適用されないことを除き、他のロガーと同じで
  す。

* *incremental* - この環境設定が既存の環境設定に対する増分として解釈
  さ れるかどうかです。この値のデフォルトは "False" で、指定された環境
  設 定は、既存の "fileConfig()" API によって使われているのと同じ意味
  上で 、既存の環境設定を置き換えます。

  指定された値が "True" なら、環境設定は 増分設定 の節で記述されている
  ように進行します。

* *disable_existing_loggers* - 既存のロガーをすべて無効にするべきか
  ど うかです。この設定は、 "fileConfig()" における同じ名前のパラメー
  タと 同じです。設定されていなければ、このパラメータのデフォルトは
  "True" です。この値は、 *incremental* が "True" なら無視されます。


15.8.2.2. 増分設定
------------------

増分設定に完全な柔軟性を提供するのは難しいです。例えば、フィルタやフォ
ーマッタのようなオブジェクトは匿名なので、一旦環境設定がなされると、設
定を拡張するときにそのような匿名オブジェクトを参照することができません
。

さらに、一旦環境設定がなされた後、実行時にロガー、ハンドラ、フィルタ、
フォーマッタのオブジェクトグラフを任意に変えなければならない例もありま
せん。ロガーとハンドラの冗長性は、レベル (または、ロガーの場合には、伝
播フラグ) を設定することによってのみ制御できます。安全な方法でオブジェ
クトグラフを任意に変えることは、マルチスレッド環境で問題となります。不
可能ではないですが、その効用は実装に加えられる複雑さに見合いません。

従って、環境設定辞書の "incremental" キーが与えられ、これが "True" で
あるとき、システムは "formatters" と "filters" の項目を完全に無視し、
"handlers" の項目の "level" 設定と、"loggers" と "root" の項目の
"level" と "propagate" 設定のみを処理します。

環境設定辞書の値を使うことで、設定は pickle 化された辞書としてネットワ
ークを通してソケットリスナに送ることができます。これにより、長時間起動
するアプリケーションのロギングの冗長性を、アプリケーションを止めて再起
動する必要なしに、いつでも変更することができます。


15.8.2.3. オブジェクトの接続
----------------------------

このスキーマは、ロギングオブジェクトの一揃い - ロガー、ハンドラ、フォ
ーマッタ、フィルタ - について記述します。これらは、オブジェクトグラフ
上でお互い接続されます。従って、このスキーマは、オブジェクト間の接続を
表現しなければなりません。例えば、環境設定で、特定のロガーが特定のハン
ドラに取り付けられたとします。この議論では、ロガーとハンドラが、これら
2 つの接続のそれぞれ送信元と送信先であるといえます。もちろん、この設定
オブジェクト中では、これはハンドラへの参照を保持しているロガーで表され
ます。設定辞書中で、これは次のようになされます。まず、送信先オブジェク
トを曖昧さなく指定する id を与えます。そして、その id を送信元オブジェ
クトの環境設定で使い、送信元とその id をもつ送信先が接続されていること
を示します。

ですから、例えば、以下の YAML のコード片を例にとると:

   formatters:
     brief:
       # configuration for formatter with id 'brief' goes here
     precise:
       # configuration for formatter with id 'precise' goes here
   handlers:
     h1: #This is an id
      # configuration of handler with id 'h1' goes here
      formatter: brief
     h2: #This is another id
      # configuration of handler with id 'h2' goes here
      formatter: precise
   loggers:
     foo.bar.baz:
       # other configuration for logger 'foo.bar.baz'
       handlers: [h1, h2]

(注釈: YAML がここで使われているのは、辞書の等価な Python 形式よりもこ
ちらのほうが少し読みやすいからです。)

ロガーの id は、プログラム上でロガーへの参照を得るために使われるロガー
名で、たとえば "foo.bar.baz" です。フォーマッタとフィルタの id は、(上
の "brief", "precise" のような) 任意の文字列値にできます。これらは一時
的なもので、環境設定辞書の処理にのみ意味があり、オブジェクト間の接続を
決定するのに使われます。また、これらは設定の呼び出しが完了したとき、ど
こにも残りません。

上記のコード片は、"foo.bar.baz" というの名ロガーに、ハンドラ id "h1"
と "h2" で表される 2 つのハンドラを接続することを示します。"h1" のフォ
ーマッタは id "brief" で記述されるもので、"h2" のフォーマッタは id
"precise" で記述されるものです。


15.8.2.4. ユーザ定義オブジェクト
--------------------------------

このスキーマは、ハンドラ、フィルタ、フォーマッタのための、ユーザ定義オ
ブジェクトをサポートします。(ロガーは、異なるインスタンスに対して異な
る型を持つ必要はないので、この環境設定スキーマは、ユーザ定義ロガークラ
スをサポートしていません。)

設定されるオブジェクトは、それらの設定を詳述する辞書によって記述されま
す。場所によっては、あるオブジェクトがどのようにインスタンス化されるか
というコンテキストを、ロギングシステムが推測できます。しかし、ユーザ定
義オブジェクトがインスタンス化されるとき、システムはどのようにこれを行
うかを知りません。ユーザ定義オブジェクトのインスタンス化を完全に柔軟な
ものにするため、ユーザは 'ファクトリ' - 設定辞書を引数として呼ばれ、イ
ンスタンス化されたオブジェクトを返す呼び出し可能オブジェクト - を提供
する必要があります。これは特殊キー "'()'" で利用できる、ファクトリへの
絶対インポートパスによって合図されます。ここに具体的な例を挙げます:

   formatters:
     brief:
       format: '%(message)s'
     default:
       format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
       datefmt: '%Y-%m-%d %H:%M:%S'
     custom:
         (): my.package.customFormatterFactory
         bar: baz
         spam: 99.9
         answer: 42

上記の YAML コード片は 3 つのフォーマッタを定義します。 1 つ目は、id
が "brief" で、指定されたフォーマット文字列をもつ、標準
"logging.Formatter" インスタンスです。 2 つ目は、id が "default" で、
長いフォーマットを持ち、時間フォーマットも定義していて、結果はその 2
つのフォーマット文字列で初期化された "logging.Formatter" になります。
Python ソース形式で見ると、 "brief" と "default" フォーマッタは、それ
ぞれ設定の部分辞書:

   {
     'format' : '%(message)s'
   }

および:

   {
     'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
     'datefmt' : '%Y-%m-%d %H:%M:%S'
   }

を持ち、これらの辞書が特殊キー "'()'" を持たないので、インスタンス化は
コンテキストから推測され、結果として標準の "logging.Formatter" インス
タンスが生成されます。id が "custom" である、3 つ目のフォーマッタの設
定をする部分辞書は:

   {
     '()' : 'my.package.customFormatterFactory',
     'bar' : 'baz',
     'spam' : 99.9,
     'answer' : 42
   }

で、ユーザ定義のインスタンス化が望まれることを示す特殊キー "'()'" を含
みます。この場合、指定された呼び出し可能ファクトリオブジェクトが使われ
ます。これが実際の呼び出し可能オブジェクトであれば、それが直接使われま
す - そうではなく、(この例でのように) 文字列を指定したなら、実際の呼び
出し可能オブジェクトは、通常のインポート機構を使って検索されます。その
呼び出し可能オブジェクトは、環境設定の部分辞書の、**残りの** 要素をキ
ーワード引数として呼ばれます。上記の例では、id が "custom" のフォーマ
ッタは、以下の呼び出しによって返されるものとみなされます:

   my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)

キー "'()'" が特殊キーとして使われるのは、キーワードパラメータ名として
不正で、呼び出しに使われるキーワード引数と衝突し得ないからです。"'()'"
はまた、対応する値が呼び出し可能オブジェクトであると覚えやすくします。


15.8.2.5. 外部オブジェクトへのアクセス
--------------------------------------

環境設定が、例えば "sys.stderr" のような、設定の外部のオブジェクトへの
参照を必要とすることがあります。設定辞書が Python コードで構成されてい
れば話は簡単ですが、これがテキストファイル (JSON, YAML 等) を通して提
供されていると問題となります。テキストファイルでは、"sys.stderr" をリ
テラル文字列 "'sys.stderr'" と区別する標準の方法がありません。この区別
を容易にするため、環境設定システムは、文字列中の特定の特殊接頭辞を見つ
け、それらを特殊に扱います。例えば、リテラル文字列
"'ext://sys.stderr'" が設定中の値として与えられたら、この "ext://" は
剥ぎ取られ、この値の残りが普通のインポート機構で処理されます。

このような接頭辞の処理は、プロトコルの処理と同じようになされます。どち
らの機構も、正規表現 "^(?P<prefix>[a-z]+)://(?P<suffix>.*)$" にマッチ
する接頭辞を検索し、それによって "prefix" が認識されたなら、接頭辞に応
じたやり方で "suffix" が処理され、その処理の結果によって文字列値が置き
換えられます。接頭辞が認識されなければ、その文字列値はそのまま残されま
す。


15.8.2.6. 内部オブジェクトへのアクセス
--------------------------------------

外部オブジェクトと同様、環境設定内部のオブジェクトへのアクセスを必要と
することもあります。これは、その各オブジェクトを司る環境設定システムに
よって暗黙に行われます。例えば、ロガーやハンドラの "level" に対する文
字列値 "'DEBUG'" は、自動的に値 "logging.DEBUG" に変換されますし、
"handlers", "filters" および "formatter" の項目は、オブジェクト id を
取って、適切な送信先オブジェクトを決定します。

しかし、ユーザ定義モジュールには、 "logging" モジュールには分からない
ような、より一般的な機構が必要です。例えば、
"logging.handlers.MemoryHandler" があって、委譲する先の別のハンドラで
ある "target" 引数を取るとします。システムはこのクラスをすでに知ってい
ますから、設定中で、与えられた "target" は関連するターゲットハンドラの
オブジェクト id でさえあればよく、システムはその id からハンドラを決定
します。しかし、ユーザが "my.package.MyHandler" を定義して、それが
"alternate" ハンドラを持つなら、設定システムは "alternate" がハンドラ
を参照していることを知りません。これを知らせるのに、一般的な解析システ
ムで、ユーザはこのように指定できます:

   handlers:
     file:
       # configuration of file handler goes here

     custom:
       (): my.package.MyHandler
       alternate: cfg://handlers.file

リテラル文字列 "'cfg://handlers.file'" は、"ext://" 接頭辞が付いた文字
列と同じように分析されますが、インポート名前空間ではなく、環境設定自体
が検索されます。この機構は "str.format" でできるのと同じようにドットや
インデックスのアクセスができます。従って、環境設定において以下のコード
片が与えられれば:

   handlers:
     email:
       class: logging.handlers.SMTPHandler
       mailhost: localhost
       fromaddr: my_app@domain.tld
       toaddrs:
         - support_team@domain.tld
         - dev_team@domain.tld
       subject: Houston, we have a problem.

文字列 "'cfg://handlers'" は、キー "handlers" をもつ辞書であると分析さ
れ、文字列 "'cfg://handlers.email'" は、"handlers" 辞書内の、"email"
キーをもつ辞書であると分析されます。文字列
"'cfg://handlers.email.toaddrs[1]" は、"'dev_team@domain.tld'" と分析
され、"'cfg://handlers.email.toaddrs[0]'" は値
"'support_team@domain.tld'" と分析されます。"subject" の値には、
"'cfg://handlers.email.subject'" または等価な
"'cfg://handlers.email[subject]'" でアクセスできます。後者が必要なのは
、キーがスペースや非アルファベット文字を含むときのみです。インデックス
値が十進数字のみで構成されているなら、まず対応する整数値を使ってアクセ
スが試みられ、必要なら文字列値で代替します。

文字列 "cfg://handlers.myhandler.mykey.123" が与えられると、これは
"config_dict['handlers']['myhandler']['mykey']['123']" と分析されます
。文字列が "cfg://handlers.myhandler.mykey[123]" と指定されたら、シス
テムは "config_dict['handlers']['myhandler']['mykey'][123]" から値を引
き出そうとし、失敗したら
"config_dict['handlers']['myhandler']['mykey']['123']" で代替します。


15.8.2.7. インポート解決とカスタムインポーター
----------------------------------------------

インポート解決は、デフォルトではインポートを行うために "__import__()"
組み込み関数を使用します。これを独自のインポートメカニズムに置き換えた
いと思うかもしれません: もしそうなら、 "DictConfigurator" あるいはその
上位クラスである "BaseConfigurator" クラスの "importer" 属性を置換する
ことができます。ただし、この関数はクラスからディスクリプタ経由でアクセ
スされる点に注意する必要があります。インポートを行うために Python
callable を使用していて、それをインスタンスレベルではなくクラスレベル
で定義したければ、 "staticmethod()" でそれをラップする必要があります。
例えば:

   from importlib import import_module
   from logging.config import BaseConfigurator

   BaseConfigurator.importer = staticmethod(import_module)

configurator *インスタンス* に対してインポート callable をセットする場
合は、 "staticmethod()" でラップする必要はありません。


15.8.3. 環境設定ファイルの書式
==============================

"fileConfig()" が解釈できる環境設定ファイルの形式は、 "configparser"
の機能に基づいています。ファイルには、 "[loggers]", "[handlers]",
"[formatters]" といったセクションが入っていなければならず、各セクショ
ンではファイル中で定義されている各タイプのエンティティを名前で指定して
います。こうしたエンティティの各々について、そのエンティティをどう設定
するかを示した個別のセクションがあります。すなわち、 "log01" という名
前の "[loggers]" セクションにあるロガーに対しては、対応する詳細設定が
セクション "[logger_log01]" に収められています。同様に、 "hand01" とい
う名前の "[handlers]" セクションにあるハンドラは "[handler_hand01]" と
呼ばれるセクションに設定をもつことになり、 "[formatters]" セクションに
ある "form01" は "[formatter_form01]" というセクションで設定が指定され
ています。ルートロガーの設定は "[logger_root]" と呼ばれるセクションで
指定されていなければなりません。

注釈: "fileConfig()" API は "dictConfig()" API よりも古く、ロギング
  のある 種の側面についてカバーする機能に欠けています。たとえば
  "fileConfig()" では数値レベルを超えたメッセージを単に拾うフィルタリ
  ングを行う "Filter" オブジェクトを構成出来ません。 "Filter" のインス
  タンスをロギングの設定において持つ必要があるならば、 "dictConfig()"
  を使う必要があるでしょう。設定の機能における将来の拡張は
  "dictConfig()" に対して行われることに注意してください。ですから、そ
  うするのが便利であるときに新しい API に乗り換えるのは良い考えです。

ファイルにおけるこれらのセクションの例を以下に示します。

   [loggers]
   keys=root,log02,log03,log04,log05,log06,log07

   [handlers]
   keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09

   [formatters]
   keys=form01,form02,form03,form04,form05,form06,form07,form08,form09

ルートロガーでは、レベルとハンドラのリストを指定しなければなりません。
ルートロガーのセクションの例を以下に示します。

   [logger_root]
   level=NOTSET
   handlers=hand01

"level" エントリは "DEBUG, INFO, WARNING, ERROR, CRITICAL" のうちの一
つか、 "NOTSET" になります。ルートロガーの場合にのみ、 "NOTSET" はすべ
てのメッセージがログ記録されることを意味します。レベル値は "logging"
パッケージの名前空間のコンテキストにおいて "eval()" されます。

"handlers" エントリはコンマで区切られたハンドラ名からなるリストで、
"[handlers]" セクションになくてはなりません。また、これらの各ハンドラ
の名前に対応するセクションが設定ファイルに存在しなければなりません。

ルートロガー以外のロガーでは、いくつか追加の情報が必要になります。これ
は以下の例のように表されます。

   [logger_parser]
   level=DEBUG
   handlers=hand01
   propagate=1
   qualname=compiler.parser

"level" および "handlers" エントリはルートロガーのエントリと同様に解釈
されますが、非ルートロガーのレベルが "NOTSET" に指定された場合、ロギン
グシステムはロガー階層のより上位のロガーにロガーの実効レベルを問い合わ
せるところが違います。"propagate" エントリは、メッセージをロガー階層に
おけるこのロガーの上位のハンドラに伝播させることを示す 1 に設定される
か、メッセージを階層の上位に伝播 **しない** ことを示す 0 に設定されま
す。"qualname" エントリはロガーのチャネル名を階層的に表したもの、すな
わちアプリケーションがこのロガーを取得する際に使う名前になります。

ハンドラの環境設定を指定しているセクションは以下の例のようになります。

   [handler_hand01]
   class=StreamHandler
   level=NOTSET
   formatter=form01
   args=(sys.stdout,)

"class" エントリはハンドラのクラス ("logging" パッケージの名前空間にお
いて "eval()" で決定されます) を示します。 "level" はロガーの場合と同
じように解釈され、 "NOTSET" は "すべてを記録する (log everything)" と
解釈されます。

バージョン 2.6 で変更: ハンドラクラスのドット区切りモジュールおよびク
ラス名としての解決のサポートが追加されました。

"formatter" エントリはこのハンドラのフォーマッタに対するキー名を表しま
す。空文字列の場合、デフォルトのフォーマッタ
("logging._defaultFormatter") が使われます。名前が指定されている場合、
その名前は "[formatters]" セクションになくてはならず、対応するセクショ
ンが設定ファイル中になければなりません。

"args" エントリは、 "logging" パッケージの名前空間のコンテキストで
"eval()" される際、ハンドラクラスのコンストラクタに対する引数からなる
リストになります。典型的なエントリがどうやって作成されるかについては、
対応するハンドラのコンストラクタか、以下の例を参照してください。

   [handler_hand02]
   class=FileHandler
   level=DEBUG
   formatter=form02
   args=('python.log', 'w')

   [handler_hand03]
   class=handlers.SocketHandler
   level=INFO
   formatter=form03
   args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)

   [handler_hand04]
   class=handlers.DatagramHandler
   level=WARN
   formatter=form04
   args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)

   [handler_hand05]
   class=handlers.SysLogHandler
   level=ERROR
   formatter=form05
   args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)

   [handler_hand06]
   class=handlers.NTEventLogHandler
   level=CRITICAL
   formatter=form06
   args=('Python Application', '', 'Application')

   [handler_hand07]
   class=handlers.SMTPHandler
   level=WARN
   formatter=form07
   args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')

   [handler_hand08]
   class=handlers.MemoryHandler
   level=NOTSET
   formatter=form08
   target=
   args=(10, ERROR)

   [handler_hand09]
   class=handlers.HTTPHandler
   level=NOTSET
   formatter=form09
   args=('localhost:9022', '/log', 'GET')

フォーマッタの環境設定を指定しているセクションは以下のような形式です。

   [formatter_form01]
   format=F1 %(asctime)s %(levelname)s %(message)s
   datefmt=
   class=logging.Formatter

"format" エントリは全体を書式化する文字列で、 "datefmt" エントリは
"strftime()" 互換の日付/時刻書式化文字列です。空文字列の場合、パッケー
ジによって ISO8601 形式の日付/時刻に置き換えられ、日付書式化文字列
"\'%Y-%m-%d %H:%M:%S\'" を指定した場合とほとんど同じになります。
ISO8601 形式ではミリ秒も指定しており、上の書式化文字列の結果にカンマで
区切って追加されます。 ISO8601 形式の時刻の例は "2003-01-23
00:29:50,411" です。

"class" エントリはオプションです。これはフォーマッタクラスの名前を (モ
ジュール名とクラス名をドットでつないだもので) 指し示すものです。このオ
プションは "Formatter" の子クラスをインスタンス化するのに便利です。
"Formatter" の子クラスが、展開もしくは要約された形式の例外トレースバッ
クを表示することができます。

注釈: "eval()" を使用していることで、上述のようにソケット経由で設定
  を送受 信するために "listen()" を使用していることに起因する潜在的な
  セキュリ ティリスクがあります。そのリスクは、相互に信頼できない多数
  のユーザが 同じマシン上でコードを実行する場合に制限されています; 詳
  細は "listen()" ドキュメンテーションを参照してください。

参考:

  "logging" モジュール
     logging モジュールの API リファレンス。

  "logging.handlers" モジュール
     logging モジュールに含まれる、便利なハンドラです。
