# `logging.config` --- Logging configuration

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

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

## 環境設定のための関数

以下の関数は 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()

  For example, a subclass of `DictConfigurator` could call `DictConfigurator.__init__()` in its own `__init__()`, then set up custom prefixes which would be usable in the subsequent `configure()` call. `dictConfigClass` would be bound to this new subclass, and then `dictConfig()` could be called exactly as in the default, uncustomized state.

  バージョン 3.2 で追加.

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

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

  It will raise `FileNotFoundError` if the file doesn't exist and `RuntimeError` if the file is invalid or empty.

  パラメータ:

    - fname -- A filename, or a file-like object, or an instance derived from `RawConfigParser`. If a `RawConfigParser`-derived instance is passed, it is used as is. Otherwise, a `ConfigParser` is instantiated, and the configuration read by it from the object passed in `fname`. If that has a `readline()` method, it is assumed to be a file-like object and read using `read_file()`; otherwise, it is assumed to be a filename and passed to `read()`.

    - defaults -- Defaults to be passed to the `ConfigParser` can be specified in this argument.

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

    - encoding -- fname がファイル名の場合に、ファイルをオープンする時のエンコーディングです。

  バージョン 3.4 で変更: `fname` として `RawConfigParser` のサブクラスのインスタンスが渡せ得るようになっています。これによってこのようなことが容易になります:

  > - ロギングの設定が、アプリケーション全体の設定における単なる一部であるような設定ファイルの使用。

  > - ファイルから設定を読み込み、 `fileConfig` に通す前に(例えばコマンドラインパラメータやランタイム環境の他のなにかで)アプリケーションによって修正するようなこと。

  バージョン 3.10 で変更: Added the encoding parameter.

  バージョン 3.11.4 で変更: An exception will be thrown if the provided file doesn't exist or is invalid or empty.

logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)

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

  `verify` 引数を指定する場合は、これはソケットを通して受け取ったバイト文字列が妥当であるか、処理すべきであるかどうかを検査する callable である必要があります。ソケットを通じて、暗号化または署名あるいはその両方を受け取ることがあります。そのような場合に、 `verify` callable が署名の正当性検査または暗号化の復号あるいはその両方を実施することが出来ます。 `verify` callable は単一引数で呼び出されます - ソケットを通じて受け取ったバイト文字列です - そして処理すべきバイト文字列、または捨て去られるべきであることを示すための `None` を返す必要があります。返却されるバイト文字列は(たとえば正当性検査だけが行われて)渡されたものと同じかもしれませんし、あるいは(おそらく暗号化の復号が行われて)まったく異なるものかもしれません。

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

  注釈

  設定の一部は `eval()` を通じて渡されるため、この関数を利用することはユーザーをセキュリティ上のリスクにさらす可能性があります。この関数は `localhost` のソケットだけにバインドされており、リモートマシンからの接続を受け付けませんが、それでも `listen()` を呼び出したプロセスのアカウントのもとで信頼できないコードが実行されうるシナリオが存在します。特に、 `listen()` を呼び出したプロセスが複数のユーザーが利用するマシン上で実行されており、ユーザー同士が互いに信頼できない場合、悪意あるユーザーが被害者ユーザーのプロセス上で本質的に任意のコードを実行するように計画する可能性があります。攻撃は、単に被害者ユーザーの `listen()` ソケットに接続して、被害者ユーザーのプロセス上で攻撃者が実行したいコードが実行されるような設定を送り込むだけです。この攻撃はデフォルトのポートが使われている場合きわめて容易であり、異なるポートが使われている場合でもそれほど難しくはありません。このような事象が発生するリスクを回避するためには、 `listen()` の `verify` 引数を使って不正な設定が適用されるのを防ぐようにしてください。

  バージョン 3.4 で変更: `verify` 引数が追加されました。

  注釈

  既存のロガーを無効にしない構成をリスナーに送信する場合は、設定にはJSONフォーマットを使用する必要があります。これは、設定に `dictConfig()` を使用します。 このメソッドを使用すると、 `disable_existing_loggers` に `False` を指定した設定を送信できます。

logging.config.stopListening()

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

## セキュリティで考慮すべき点

logging の設定機能は便利さを提供します。その便利さの一部は設定ファイル内のテキストを logging の設定に使われる Python オブジェクトに変換する機能を提供することによって実現されています - たとえば、 ユーザ定義オブジェクト で説明されているような機能です。しかし、まさにこのメカニズム (実行可能オブジェクトをユーザー定義モジュールからインポートし、設定ファイルから読み込んだパラメータを使ってそれらを呼び出すこと) が任意のコードを呼び出すことに利用できる可能性があります。そして、この理由により、信頼できない情報源から取得した設定ファイルは 細心の注意 を払って取り扱わなければなりません。そのようなファイルをロードする場合、そのファイルがいかなる問題も起こさないと確認した上で実際にファイルをロードしてください。

## 環境設定辞書スキーマ

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

### 辞書スキーマの詳細

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

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

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

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

  設定辞書は `Formatter` オブジェクトを作成するときの引数に対応する、次のようなオプションキーがないか探索されます。

  - `format`

  - `datefmt`

  - `style`

  - `validate` (バージョン3.8以降)

  オプションの `class` キーはフォーマッタークラスの名前を表します（モジュールとクラス名をドットで繋げる）。インスタンス化時の引数は `Formatter` と同じであるため、このキーは `Formatter` をカスタマイズしたサブクラスのインスタンス化に使うのがもっとも便利です。例えばトレースバックにさらに情報を付加したり、情報を要約代替クラスを実装するといったことが想定されます。もし、自作のフォーマッターが異なる引数や追加の設定引数を持つ場合は、 ユーザ定義オブジェクト を使うべきです。

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

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

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

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

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

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

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

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

    バージョン 3.11 で変更: `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 のリストです。

    バージョン 3.11 で変更: `filters` は id に加えてフィルタのインスタンスを受け取ることができるようになりました。

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

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

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

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

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

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

### 増分設定

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

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

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

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

### オブジェクトの接続

このスキーマは、ロギングオブジェクトの一揃い - ロガー、ハンドラ、フォーマッタ、フィルタ - について記述します。これらは、オブジェクトグラフ上でお互い接続されます。従って、このスキーマは、オブジェクト間の接続を表現しなければなりません。例えば、環境設定で、特定のロガーが特定のハンドラに取り付けられたとします。この議論では、ロガーとハンドラが、これら 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` で記述されるものです。

### ユーザ定義オブジェクト

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

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

    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)

警告

上記の例で `bar`, `spam` または `answer` のようなキーワード引数に指定する値は、設定作業の途中で処理されることなくそのまま呼び出し可能オブジェクトに渡されるため、 `cfg://foo` や `ext://bar` のような設定用の辞書や参照であってはいけません。

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

バージョン 3.11 で変更: `handlers` と `loggers` の `filters` メンバーは id に加えてフィルタのインスタンスを受け取ることができるようになりました。

特殊なキーワード `'.'` を指定することもできます。この場合その値には属性名とその値のマッピングをあらわす辞書を指定します。指定された属性は、もしそれが見つかった場合、戻り値のユーザー定義オブジェクトに設定されます。したがって、以下のように設定すると:

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

戻り値のフォーマッタは属性 `foo` と``baz`` をもち、それぞれの値は `'bar'` と `'bozz'` に設定されます。

警告

上記の例で `foo` や `baz` のような属性に設定する値は、フォーマッタの設定作業の途中で処理されることなくそのまま属性値として設定されるため、 `cfg://foo` や `ext://bar` のような設定用の辞書や参照であってはいけません。

### ハンドラの設定順序

ハンドラは対応するキーのアルファベット順に設定され、設定されたハンドラはスキーマ中の環境設定辞書における `handlers` 辞書 (の作業コピー) を差し替えます。たとえば `cfg://handlers.foo` という設定において、最初に `handlers['foo']``が ``foo` という名前のハンドラに対する環境設定辞書を指しているとき、以後 (いったんハンドラが設定されると) 設定されたハンドラのインスタンスを指すようになります。その結果、 `cfg://handlers.foo` は辞書かハンドラのインスタンスのいずれかに解決される可能性があります。一般に、ハンドラは、依存するハンドラが全て設定された _あとに_ それらに依存するハンドラが設定されるように名前をつける方が賢明です; これにより、 `foo` という名前のハンドラに依存するハンドラを設定する際に `cfg://handlers.foo` で依存するハンドラを参照できるようになります。もし依存するハンドラの名前が `bar` であった場合、アルファベット順の規則から `bar` の設定が `foo` の設定よりも先に試みられることにより `foo` がまだ設定されていないかもしれないことから、問題が起こる可能性があります。一方、依存するハンドラの名前が `foobar` であった場合は、その設定は `foo` の後に行われることとなり、 `cfg://handlers.foo` は環境設定辞書ではなく設定済みのハンドラ `foo` のインスタンスに解決されます。

### 外部オブジェクトへのアクセス

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

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

### 内部オブジェクトへのアクセス

外部オブジェクトと同様、環境設定内部のオブジェクトへのアクセスを必要とすることもあります。これは、その各オブジェクトを司る環境設定システムによって暗黙に行われます。例えば、ロガーやハンドラの `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.

in the configuration, the string `'cfg://handlers'` would resolve to the dict with key `handlers`, the string `'cfg://handlers.email` would resolve to the dict with key `email` in the `handlers` dict, and so on. The string `'cfg://handlers.email.toaddrs[1]` would resolve to `'dev_team@domain.tld'` and the string `'cfg://handlers.email.toaddrs[0]'` would resolve to the value `'support_team@domain.tld'`. The `subject` value could be accessed using either `'cfg://handlers.email.subject'` or, equivalently, `'cfg://handlers.email[subject]'`. The latter form only needs to be used if the key contains spaces or non-alphanumeric characters. If an index value consists only of decimal digits, access will be attempted using the corresponding integer value, falling back to the string value if needed.

文字列 `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']` で代替します。

### インポート解決とカスタムインポーター

インポート解決は、デフォルトではインポートを行うために `__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()` でラップする必要はありません。

## 環境設定ファイルの書式

`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` パッケージの名前空間のコンテキストで 評価 されます。

`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)" と解釈されます。

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

`args` は、 `logging` パッケージの名前空間のコンテキストで 評価 される時点では、ハンドラークラスのコンストラクタのための引数のリストです。典型的なコンストラクタの引数が生成される方法については、各ハンドラのコンストラクタまたは下記の例を参照してください。指定されなければデフォルトは `()` になります。

オプションの `kwargs` は、 `logging` パッケージの名前空間のコンテキストで 評価 される時点では、ハンドラークラスのコンストラクタのためのキーワード引数の辞書です。指定されなければデフォルトは `{}` になります。

    [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')
    kwargs={'timeout': 10.0}

    [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')
    kwargs={'secure': True}

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

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

フォーマッターのセクション の辞書スキーマと同じキーを持つ、フォーマッター設定の引数です。

注釈

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

参考

`logging` モジュール

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

`logging.handlers` モジュール

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