# 7.8. `codecs` --- codec レジストリと基底クラス

このモジュールでは、内部的な Python codec レジストリに対するアクセス手段を提供しています。codec レジストリは、標準の Python codec(エンコーダとデコーダ)の基底クラスを定義し、 codec およびエラー処理の検索手順を管理しています。

`codecs` では以下の関数を定義しています:

`codecs.``encode`(obj[, encoding[, errors]])

  encoding に記載された codec を使用して obj をエンコードします。デフォルトのエンコーディングは `'ascii'` です。

  希望のエラー処理スキームを errors に設定することができます。デフォルトのエラーハンドラは `'strict'` です。これはエンコードエラーは `ValueError` (もしくは `UnicodeEncodeError` のような、より codec に固有のサブクラス) を送出することを意味します。codec エラー処理についてのより詳しい情報は Codec 基底クラス を参照してください。

  バージョン 2.4 で追加.

`codecs.``decode`(obj[, encoding[, errors]])

  encoding に記載された codec を使用して obj をデコードします。デフォルトのエンコーディングは `'ascii'` です。

  希望のエラー処理スキームを errors に設定することができます。デフォルトのエラーハンドラは `'strict'` です。これはデコードエラーは `ValueError` (もしくは `UnicodeDecodeError` のような、より codec に固有のサブクラス) を送出することを意味します。codec エラー処理についてのより詳しい情報は Codec 基底クラス を参照してください。

  バージョン 2.4 で追加.

`codecs.``register`(search_function)

  codec 検索関数を登録します。検索関数は第 1 引数にアルファベットの小文字から成るエンコーディング名を取り、以下の属性を持つ `CodecInfo` オブジェクトを返します:

  - `name` エンコーディング名;
  - `encode` 内部状態を持たないエンコード関数;
  - `decode` 内部状態を持たないデコード関数;
  - `incrementalencoder` 漸増的エンコーダクラスまたはファクトリ関数;
  - `incrementaldecoder` 漸増的デコーダクラスまたはファクトリ関数;
  - `streamwriter` ストリームライタクラスまたはファクトリ関数;
  - `streamreader` ストリームリーダクラスまたはファクトリ関数。

  種々の関数やクラスが以下の引数をとります:

  encode と decode: これらの引数は、 Codec インスタンスの `encode()` と `decode()` と同じインタフェースを持つ関数、またはメソッドでなければなりません (Codec Interface 参照) 。これらの関数・メソッドは内部状態を持たずに動作する (stateless mode) と想定されています。

  incrementalencoder と incrementaldecoder: これらは以下のインタフェースを持つファクトリ関数でなければなりません:

  > `factory(errors='strict')`

  ファクトリ関数は、それぞれ基底クラスの `IncrementalEncoder` や `IncrementalDecoder` が定義しているインタフェースを提供するオブジェクトを返さなければなりません。漸増的 codecs は内部状態を維持できます。

  streamreader と streamwriter: これらの引数は、次のようなインタフェースを持つファクトリ関数でなければなりません:

  > `factory(stream, errors='strict')`

  ファクトリ関数は、それぞれ基底クラスの `StreamReader` や `StreamWriter` が定義しているインタフェースを提供するオブジェクトを返さねばなりません。ストリーム codecs は内部状態を維持できます。

  errors が取り得る値は

  - `'strict'` エンコーディングエラーの際に例外を発生
  - `'replace'` 奇形データを `'?'` や `'\ufffd'` 等の適切な文字で置換
  - `'ignore'` 奇形データを無視し何も通知せずに処理を継続
  - `'xmlcharrefreplace'` 適切な XML 文字参照で置換 (エンコーディングのみ))
  - `'backslashreplace'` (バックスラッシュつきのエスケープシーケンス (エンコーディングのみ))

  と `register_error()` で定義されたその他のエラー処理名になります。

  検索関数は、与えられたエンコーディングを見つけられなかった場合、 `None` を返さなければなりません。

`codecs.``lookup`(encoding)

  Python codec レジストリから codec 情報を探し、上で定義したような `CodecInfo` オブジェクトを返します。

  エンコーディングの検索は、まずレジストリのキャッシュから行います。見つからなければ、登録されている検索関数のリストから探します。 `CodecInfo` オブジェクトが一つも見つからなければ `LookupError` を送出します。見つかったら、その `CodecInfo` オブジェクトはキャッシュに保存され、呼び出し側に返されます。

さまざまな codec へのアクセスを簡便化するために、このモジュールは以下のような関数を提供しています。これらの関数は、 codec の検索に `lookup()` を使います:

`codecs.``getencoder`(encoding)

  与えられたエンコーディングに対する codec を検索し、エンコーダ関数を返します。

  エンコーディングが見つからなければ `LookupError` を送出します。

`codecs.``getdecoder`(encoding)

  与えられたエンコーディングに対する codec を検索し、デコーダ関数を返します。

  エンコーディングが見つからなければ `LookupError` を送出します。

`codecs.``getincrementalencoder`(encoding)

  与えられたエンコーディングに対する codec を検索し、漸増的エンコーダクラスまたはファクトリ関数を返します。

  エンコーディングが見つからないか、 codec が漸増的エンコーダをサポートしなければ `LookupError` を送出します。

  バージョン 2.5 で追加.

`codecs.``getincrementaldecoder`(encoding)

  与えられたエンコーディングに対する codec を検索し、漸増的デコーダクラスまたはファクトリ関数を返します。

  エンコーディングが見つからないか、 codec が漸増的デコーダをサポートしなければ `LookupError` を送出します。

  バージョン 2.5 で追加.

`codecs.``getreader`(encoding)

  与えられたエンコーディングに対する codec を検索し、StreamReader クラスまたはファクトリ関数を返します。

  エンコーディングが見つからなければ `LookupError` を送出します。

`codecs.``getwriter`(encoding)

  与えられたエンコーディングに対する codec を検索し、StreamWriter クラスまたはファクトリ関数を返します。

  エンコーディングが見つからなければ `LookupError` を送出します。

`codecs.``register_error`(name, error_handler)

  エラー処理関数 error_handler を名前 name で登録します。エンコード中およびデコード中にエラーが送出された場合、 errors パラメタに name を指定していれば error_handler を呼び出すようになります。

  エンコード時の error_handler はエラーの場所に関する情報の入った `UnicodeEncodeError` インスタンスとともに呼び出されます。エラー処理関数はこの例外を送出するか、別の例外を送出するか、または入力のエンコードができなかった部分の代替文字列とエンコードを再開する場所の指定が入ったタプルを返すかしなければなりません。最後の場合、エンコーダは代替文字列をエンコードし、元の入力中の指定位置からエンコードを再開します。位置を負の値にすると、入力文字列の末端からの相対位置として扱われます。境界の外側にある位置を返した場合には `IndexError` が送出されます。

  デコードと翻訳は同様に働きますが、エラー処理関数に渡されるのが `UnicodeDecodeError` か `UnicodeTranslateError` である点と、エラー処理関数の置換した内容が直接出力になる点が異なります。

`codecs.``lookup_error`(name)

  名前 name で登録済みのエラー処理関数を返します。

  エラー処理関数が見つからなければ `LookupError` を送出します。

`codecs.``strict_errors`(exception)

  `strict` エラー処理の実装です: エンコード又はデコードエラーは各々 `UnicodeError` を送出します.

`codecs.``replace_errors`(exception)

  `replace` エラー処理の実装です: 奇形データは適切な文字列に置換されます。バイト文字列では `'?'` 、 Unicode 文字列では `'\ufffd'` に置換されます。

`codecs.``ignore_errors`(exception)

  `ignore` エラー処理の実装です: 奇形データは無視されエンコード又はデコードは何も通知せず、継続されます。

`codecs.``xmlcharrefreplace_errors`(exception)

  `xmlcharrefreplace` エラー処理の実装です(エンコードのみ): エンコードできなかった文字は適切な XML 文字参照に置き換えます。

`codecs.``backslashreplace_errors`(exception)

  `backslashreplace` エラー処理の実装です (エンコードのみ): エンコードできなかった文字はバックスラッシュつきのエスケープシーケンスに置き換えられます。

エンコードされたファイルやストリームの処理を簡便化するため、このモジュールは次のようなユーティリティ関数を定義しています:

`codecs.``open`(filename, mode[, encoding[, errors[, buffering]]])

  エンコードされたファイルを mode を使って開き、透過的なエンコード/デコードを提供するラップされたバージョンを返します。デフォルトのファイルモードは `'r'` 、つまり、読み出しモードでファイルを開きます。

  注釈

  ラップされたバージョンは、該当する codec が定義している形式のオブジェクトだけを受け付けます。多くの組み込み codec では Unicode オブジェクトです。関数の戻り値も codec に依存し、通常は Unicode オブジェクトです。

  注釈

  非バイナリモードが指定されても、ファイルは常にバイナリモードで開かれます。これは、 8-bit の値を使うエンコーディングでデータが消失するのを防ぐためです。つまり、読み出しや書き込み時に、 ``'\n'` の自動変換はされないということです。

  encoding にはファイルのエンコーディングを指定します。

  エラーハンドリングのために errors を渡すことができます。これはデフォルトでは `'strict'` で、エンコード時にエラーがあれば `ValueError` を送出します。

  buffering は組み込み関数 `open()` の場合と同じ意味を持ちます。デフォルトでは行バッファリングです。

`codecs.``EncodedFile`(file, input[, output[, errors]])

  ラップしたファイルオブジェクトを返します。このオブジェクトは透過なエンコード変換を提供します。

  ラップされたファイルに書かれた文字列は、 input に指定したエンコーディングに従って変換され、 output に指定したエンコーディングを使って string 型に変換され、元のファイルに書き込まれます。中間エンコーディングは指定された codecs に依存しますが、普通は Unicode です。

  output が与えられなければ、input がデフォルトになります。

  エラーハンドリングのために errors を渡すことができます。これはデフォルトでは `'strict'` で、エンコード時にエラーがあれば `ValueError` を送出します。

`codecs.``iterencode`(iterable, encoding[, errors])

  漸増的エンコーダを使って、 iterable から供給される入力を反復的にエンコードします。この関数は generator です。 errors は (そして他のキーワード引数も同様に) 漸増的エンコーダにそのまま引き渡されます。

  バージョン 2.5 で追加.

`codecs.``iterdecode`(iterable, encoding[, errors])

  漸増的デコーダを使って、 iterable から供給される入力を反復的にデコードします。この関数は generator です。 errors は (そして他のキーワード引数も同様に) 漸増的デコーダにそのまま引き渡されます。

  バージョン 2.5 で追加.

このモジュールは以下のような定数も定義しています。プラットフォーム依存なファイルを読み書きするのに役立ちます:

`codecs.``BOM`
`codecs.``BOM_BE`
`codecs.``BOM_LE`
`codecs.``BOM_UTF8`
`codecs.``BOM_UTF16`
`codecs.``BOM_UTF16_BE`
`codecs.``BOM_UTF16_LE`
`codecs.``BOM_UTF32`
`codecs.``BOM_UTF32_BE`
`codecs.``BOM_UTF32_LE`

  ここで定義された定数は、様々なエンコーディングの Unicode のバイトオーダマーカ (BOM) で、 UTF-16 と UTF-32 におけるデータストリームやファイルストリームのバイトオーダを指定したり、 UTF-8 における Unicode signature として使われます。 `BOM_UTF16` は `BOM_UTF16_BE` と `BOM_UTF16_LE` のいずれかで、プラットフォームのネイティブバイトオーダに依存します。 `BOM` は `BOM_UTF16` の別名です。同様に `BOM_LE` は `BOM_UTF16_LE` の、 `BOM_BE` は `BOM_UTF16_BE` の別名です。他は UTF-8 と UTF-32 エンコーディングの BOM を表します。

## 7.8.1. Codec 基底クラス

`codecs` モジュールでは、 codec のインタフェースを定義する一連の基底クラスを用意して、 Python 用 codec を簡単に自作できるようにしています。

Python で何らかの codec を使えるようにするには、状態なしエンコーダ、状態なしデコーダ、ストリームリーダ、ストリームライタの 4 つのインタフェースを定義しなければなりません。通常は、状態なしエンコーダとデコーダを再利用してストリームリーダとライタのファイル・プロトコルを実装します。

`Codec` クラスは、状態なしエンコーダ・デコーダのインタフェースを定義しています。

エラー処理の簡便化と標準化のため、`encode()` メソッドと `decode()` メソッドでは、 errors 文字列引数を指定した場合に別のエラー処理を行うような仕組みを実装してもかまいません。全ての標準 Python codec では以下の文字列が定義され、実装されています。

`値` | 意味
--- | ---
`'strict'` | `UnicodeError` (または、そのサブクラス) を送出します -- デフォルトの動作です。
`'ignore'` | その文字を無視し、次の文字から変換を再開します。
`'replace'` | 適当な文字で置換します -- Python の組み込み Unicode codec のデコード時には公式の U+FFFD REPLACEMENT CHARACTER を、エンコード時には '?' を使います。
`'xmlcharrefreplace'` | 適切な XML 文字参照で置換します (エンコードのみ)。
`'backslashreplace'` | バックスラッシュつきのエスケープシーケンスで置換します (エンコードのみ)。

codecs がエラーハンドラとして受け入れる値は `register_error()` を使って追加できます。

### 7.8.1.1. Codec オブジェクト

`Codec` クラスは以下のメソッドを定義します。これらのメソッドは、内部状態を持たないエンコーダ／デコーダ関数のインタフェースを定義します:

`Codec.``encode`(input[, errors])

  オブジェクト input エンコードし、(出力オブジェクト, 消費した長さ) のタプルを返します。 codecs は Unicode 専用ではありませんが、 Unicode の文脈では、エンコーディングは Unicode オブジェクトを特定の文字集合エンコーディング(たとえば `cp1252` や `iso-8859-1`) を使ってバイト文字列オブジェクトに変換します。

  errors は適用するエラー処理を定義します。 `'strict'` 処理がデフォルトです。

  このメソッドは `Codec` に内部状態を保存してはなりません。効率よくエンコードするために状態を保持しなければならないような codecs には `StreamWriter` を使ってください。

  エンコーダは長さが 0 の入力を処理できなければなりません。この場合、空のオブジェクトを出力オブジェクトとして返さなければなりません。

`Codec.``decode`(input[, errors])

  オブジェクト input をデコードし、(出力オブジェクト, 消費した長さ) のタプルを返します。 Unicode の文脈では、デコードは特定の文字集合エンコーディングでエンコードされた文字列を Unicode オブジェクトに変換します。

  input は `bf_getreadbuf` バッファスロットを提供するオブジェクトでなければなりません。バッファスロットを提供しているオブジェクトには Python 文字列オブジェクト、バッファオブジェクト、メモリマップファイルがあります。

  errors は適用するエラー処理を定義します。 `'strict'` 処理がデフォルトです。

  このメソッドは、 `Codec` インスタンスに内部状態を保存してはなりません。効率よくエンコード／デコードするために状態を保持しなければならないような codecs には `StreamReader` を使ってください。

  デコーダは長さが 0 の入力を処理できなければなりません。この場合、空のオブジェクトを出力オブジェクトとして返さなければなりません。

`IncrementalEncoder` クラスおよび `IncrementalDecoder` クラスはそれぞれ漸増的エンコーディングおよびデコーディングのための基本的なインタフェースを提供します。エンコーディング／デコーディングは内部状態を持たないエンコーダ／デコーダを一度呼び出すことで行なわれるのではなく、漸増的エンコーダ／デコーダの `encode()`/`decode()` メソッドを複数回呼び出すことで行なわれます。漸増的エンコーダ／デコーダはメソッド呼び出しの間エンコーディング／デコーディング処理の進行を管理します。

`encode()`/`decode()` メソッド呼び出しの出力結果をまとめたものは、入力をひとまとめにして内部状態を持たないエンコーダ／デコーダでエンコード／デコードしたものと同じになります。

### 7.8.1.2. IncrementalEncoder オブジェクト

バージョン 2.5 で追加.

`IncrementalEncoder` クラスは入力を複数ステップでエンコードするのに使われます。全ての漸増的エンコーダが Python codec レジストリと互換性を持つために定義すべきメソッドとして、このクラスには以下のメソッドが定義されています。

class `codecs.``IncrementalEncoder`([errors])

  `IncrementalEncoder` インスタンスのコンストラクタ。

  全ての漸増的エンコーダはこのコンストラクタインタフェースを提供しなければなりません。さらにキーワード引数を付け加えるのは構いませんが、Python codec レジストリで利用されるのはここで定義されているものだけです。

  `IncrementalEncoder` は errors キーワード引数を提供して異なったエラー取扱方法を実装することもできます。あらかじめ定義されているパラメータは以下の通りです:

  - `'strict'` `ValueError` (またはそのサブクラス) を送出します。これがデフォルトです。
  - `'ignore'` 一文字無視して次に進みます。
  - `'replace'` 適当な代替文字で置き換えます。
  - `'xmlcharrefreplace'` 適切な XML 文字参照に置き換えます。
  - `'backslashreplace'` バックスラッシュ付きのエスケープシーケンスで置き換えます。

  引数 errors は同名の属性に割り当てられます。属性に割り当てることで `IncrementalEncoder` オブジェクトが生きている間にエラー取扱戦略を違うものに切り替えることができるようになります。

  errors 引数に許される値の集合は `register_error()` で拡張できます。

  `encode`(object[, final])

    object を(エンコーダの現在の状態を考慮に入れて)エンコードし、得られたエンコードされたオブジェクトを返します。 `encode()` 呼び出しがこれで最後という時には final は真でなければなりません(デフォルトは偽です)。

  `reset`()

    エンコーダを初期状態にリセットします。

### 7.8.1.3. IncrementalDecoder オブジェクト

`IncrementalDecoder` クラスは入力を複数ステップでデコードするのに使われます。全ての漸増的デコーダが Python codec レジストリと互換性を持つために定義すべきメソッドとして、このクラスには以下のメソッドが定義されています。

class `codecs.``IncrementalDecoder`([errors])

  `IncrementalDecoder` インスタンスのコンストラクタ。

  全ての漸増的デコーダはこのコンストラクタインタフェースを提供しなければなりません。さらにキーワード引数を付け加えるのは構いませんが、Python codec レジストリで利用されるのはここで定義されているものだけです。

  `IncrementalDecoder` は errors キーワード引数を提供して異なったエラー取扱方法を実装することもできます。あらかじめ定義されているパラメータは以下の通りです:

  - `'strict'` `ValueError` (またはそのサブクラス) を送出します。これがデフォルトです。
  - `'ignore'` 一文字無視して次に進みます。
  - `'replace'` 適切な置換文字で置換します。

  引数 errors は同名の属性に割り当てられます。属性に割り当てることで `IncrementalDecoder` オブジェクトが生きている間にエラー取扱戦略を違うものに切り替えることができるようになります。

  errors 引数に許される値の集合は `register_error()` で拡張できます。

  `decode`(object[, final])

    object を(デコーダの現在の状態を考慮に入れて)デコードし、得られたデコードされたオブジェクトを返します。 `decode()` 呼び出しがこれで最後という時には final は真でなければなりません(デフォルトは偽です)。もし final が真ならばデコーダは入力をデコードし切り全てのバッファをフラッシュしなければなりません。そうできない場合(たとえば入力の最後に不完全なバイト列があるから)、デコーダは内部状態を持たない場合と同じようにエラーの取り扱いを開始しなければなりません(例外を送出するかもしれません)。

  `reset`()

    デコーダを初期状態にリセットします。

`StreamWriter` と `StreamReader` クラスは、新しいエンコーディングモジュールを、非常に簡単に実装するのに使用できる、一般的なインターフェイス提供します。実装例は `encodings.utf_8` をご覧ください。

### 7.8.1.4. StreamWriter オブジェクト

`StreamWriter` クラスは `Codec` のサブクラスで、以下のメソッドを定義しています。全てのストリームライタは、 Python の codec レジストリとの互換性を保つために、これらのメソッドを定義する必要があります。

class `codecs.``StreamWriter`(stream[, errors])

  `StreamWriter` インスタンスのコンストラクタです。

  全てのストリームライタはコンストラクタとしてこのインタフェースを提供しなければなりません。キーワード引数を追加しても構いませんが、Python の codec レジストリはここで定義されている引数だけを使います。

  stream は、(バイナリで) 書き込み可能なファイル類似のオブジェクトでなくてはなりません。

  `StreamWriter` は、 errors キーワード引数を受けて、異なったエラー処理の仕組みを実装しても構いません。定義済みのパラメタを以下に示します:

  - `'strict'` `ValueError` (またはそのサブクラス) を送出します。これがデフォルトです。
  - `'ignore'` 一文字無視して次に進みます。
  - `'replace'` 適当な代替文字で置き換えます。
  - `'xmlcharrefreplace'` 適切な XML 文字参照に置き換えます。
  - `'backslashreplace'` バックスラッシュ付きのエスケープシーケンスで置き換えます。

  errors 引数は、同名の属性に代入されます。この属性を変更すると、 `StreamWriter` オブジェクトが生きている間に、異なるエラー処理に変更できます。

  errors 引数に許される値の集合は `register_error()` で拡張できます。

  `write`(object)

    object の内容をエンコードしてストリームに書き出します。

  `writelines`(list)

    文字列からなるリストを連結して、(必要に応じて `write()` を何度も使って) ストリームに書き出します。

  `reset`()

    状態保持に使われていた codec のバッファを強制的に出力してリセットします。

    このメソッドが呼び出された場合、出力先データをきれいな状態にし、わざわざストリーム全体を再スキャンして状態を元に戻さなくても新しくデータを追加できるようにしなければなりません。

ここまでで挙げたメソッドの他にも、 `StreamWriter` では背後にあるストリームの他の全てのメソッドや属性を継承しなければなりません。

### 7.8.1.5. StreamReader オブジェクト

`StreamReader` クラスは `Codec` のサブクラスで、以下のメソッドを定義しています。全てのストリームリーダは、 Python の codec レジストリとの互換性を保つために、これらのメソッドを定義する必要があります。

class `codecs.``StreamReader`(stream[, errors])

  `StreamReader` インスタンスのコンストラクタです。

  全てのストリームリーダはコンストラクタとしてこのインタフェースを提供しなければなりません。キーワード引数を追加しても構いませんが、Python の codec レジストリはここで定義されている引数だけを使います。

  stream は、(バイナリで) 読み出し可能なファイル類似のオブジェクトでなくてはなりません。

  `StreamReader` は、 errors キーワード引数を受けて、異なったエラー処理の仕組みを実装しても構いません。定義済みのパラメタを以下に示します:

  - `'strict'` `ValueError` (またはそのサブクラス) を送出します。これがデフォルトです。
  - `'ignore'` 一文字無視して次に進みます。
  - `'replace'` 適切な置換文字で置換します。

  errors 引数は、同名の属性に代入されます。この属性を変更すると、 `StreamReader` オブジェクトが生きている間に、異なるエラー処理に変更できます。

  errors 引数に許される値の集合は `register_error()` で拡張できます。

  `read`([size[, chars[, firstline]]])

    ストリームからのデータをデコードし、デコード済のオブジェクトを返します。

    chars はストリームから読み込む文字数です。 `read()` は chars 以上の文字を返しませんが、それより少ない文字しか取得できない場合には chars 以下の文字を返します。

    size は、デコードするためにストリームから読み込む、およその最大バイト数を意味します。デコーダはこの値を適切な値に変更できます。デフォルト値 -1 にすると可能な限りたくさんのデータを読み込みます。 size の目的は、巨大なファイルの一括デコードを防ぐことにあります。

    firstline は、1行目さえ返せばその後の行でデコードエラーがあっても無視して十分だ、ということを示します。

    このメソッドは貪欲な読み込み戦略を取るべきです。すなわち、エンコーディング定義と size の値が許す範囲で、できるだけ多くのデータを読むべきだということです。たとえば、ストリーム上にエンコーディングの終端や状態の目印があれば、それも読み込みます。

    バージョン 2.4 で変更: chars 引数を追加しました.

    バージョン 2.4.2 で変更: firstline 引数を追加しました.

  `readline`([size[, keepends]])

    入力ストリームから1行読み込み、デコード済みのデータを返します。

    size が与えられた場合、ストリームの `read()` メソッドに size 引数として渡されます。

    keepends が偽の場合には行末の改行が削除された行が返ります。

    バージョン 2.4 で変更: keepends 引数を追加しました.

  `readlines`([sizehint[, keepends]])

    入力ストリームから全ての行を読み込み、行のリストとして返します。

    keepends が真なら、改行は、codec のデコーダメソッドを使って実装され、リスト要素の中に含まれます。

    sizehint が与えられた場合、ストリームの `read()` メソッドに size 引数として渡されます。

  `reset`()

    状態保持に使われた codec のバッファをリセットします。

    ストリームの読み位置を再設定してはならないので注意してください。このメソッドはデコードの際にエラーから復帰できるようにするためのものです。

ここまでで挙げたメソッドの他にも、 `StreamReader` では背後にあるストリームの他の全てのメソッドや属性を継承しなければなりません。

次に挙げる2つの基底クラスは、利便性のために含まれています。codec レジストリは、これらを必要としませんが、実際のところ、あると有用なものでしょう。

### 7.8.1.6. StreamReaderWriter オブジェクト

`StreamReaderWriter` を使って、読み書き両方に使えるストリームをラップできます。

`lookup()` 関数が返すファクトリ関数を使って、インスタンスを生成するという設計です。

class `codecs.``StreamReaderWriter`(stream, Reader, Writer, errors)

  `StreamReaderWriter` インスタンスを生成します。 stream はファイル類似のオブジェクトです。 Reader と Writer は、それぞれ `StreamReader` と `StreamWriter` インタフェースを提供するファクトリ関数かファクトリクラスでなければなりません。エラー処理は、ストリームリーダとライタで定義したものと同じように行われます。

`StreamReaderWriter` インスタンスは、 `StreamReader` クラスと `StreamWriter` クラスを合わせたインタフェースを継承します。元になるストリームからは、他のメソッドや属性を継承します。

### 7.8.1.7. StreamRecoder オブジェクト

`StreamRecoder` はエンコーディングデータの、フロントエンド-バックエンドを観察する機能を提供します。異なるエンコーディング環境を扱うとき、便利な場合があります。

`lookup()` 関数が返すファクトリ関数を使って、インスタンスを生成するという設計です。

class `codecs.``StreamRecoder`(stream, encode, decode, Reader, Writer, errors)

  双方向変換を実装する `StreamRecoder` インスタンスを生成します。 encode と decode はフロントエンド (`read()` への入力と `write()` からの出力) を処理し、 Reader と Writer はバックエンド (ストリームに対する読み書き) を処理します。

  これらのオブジェクトを使って、たとえば、 Latin-1 から UTF-8 、あるいは逆向きの変換を、透過に記録できます。

  stream はファイル的オブジェクトでなくてはなりません。

  encode と decode は `Codec` のインタフェースに忠実でなくてはならず、 Reader と Writer は、それぞれ `StreamReader` と `StreamWriter` のインタフェースを提供するオブジェクトのファクトリ関数かクラスでなくてはなりません。

  encode と decode はフロントエンドの変換に必要で、 Reader と Writer はバックエンドの変換に必要です。中間のフォーマットはコデックの組み合わせによって決定されます。たとえば、 Unicode コデックは中間エンコーディングに Unicode を使います。

  エラー処理はストリーム・リーダやライタで定義されている方法と同じように行われます。

`StreamRecoder` インスタンスは、 `StreamReader` と `StreamWriter` クラスを合わせたインタフェースを定義します。また、元のストリームのメソッドと属性も継承します。

## 7.8.2. エンコーディングと Unicode

Unicode 文字列は内部的にはコードポイントのシーケンスとして格納されます (正確に言えば `Py_UNICODE` 配列です)。 Python がどのようにコンパイルされたか (デフォルトである `--enable-unicode=ucs2` かまたは `--enable-unicode=ucs4` のどちらか) によって、 `Py_UNICODE` は16ビットまたは32ビットのデータ型です。 Unicode オブジェクトが CPU とメモリの外で使われることになると、 CPU のエンディアンやこれらの配列がバイト列としてどのように格納されるかが問題になってきます。 Unicode オブジェクトをバイト列に変換することをエンコーディングと呼び、バイト列から Unicode オブジェクトを再生することをデコーディングと呼びます。どのようにこの変換を行うかには多くの異なった方法があります (これらの方法のこともエンコーディングと言います) 。最も単純な方法はコードポイント 0--255 をバイト `0x0`--`0xff` に写すことです。これは `U+00FF` より上のコードポイントを持つ Unicode オブジェクトはこの方法ではエンコードできないということを意味します (この方法を `'latin-1'` とか `'iso-8859-1'` と呼びます)。 `unicode.encode()` は次のような `UnicodeEncodeError` を送出することになります: `UnicodeEncodeError: 'latin-1' codec can't encode character u'\u1234' in position 3: ordinal not in range(256)`

他のエンコーディングの一群 (charmap エンコーディングと呼ばれます) がありますが、 Unicode コードポイントの別の部分集合とこれらがどのように `0x0`--`0xff` のバイトに写されるかを選んだものです。これがどのように行なわれるかを知るには、単にたとえば `encodings/cp1252.py` (主に Windows で使われるエンコーディングです) を開いてみてください。256 文字のひとつの文字列定数がありどの文字がどのバイト値に写されるかを示しています。

これらのエンコーディングはすべて、 Unicode に定義された 1114112 のコードポイントのうちの 256 だけをエンコードすることができます。 Unicode のすべてのコードポイントを格納するための単純で直接的な方法は、各コードポイントを連続する4バイトとして格納することです。これには2つの可能性があります: ビッグエンディアンまたはリトルエンディアンの順にバイトを格納することです。これら2つのエンコーディングはそれぞれ `UTF-32-BE` および `UTF-32-LE` と呼ばれます。それらのデメリットは、例えばリトルエンディアンのマシン上で `UTF-32-BE` を使用すると、エンコードでもデコードでも常にバイト順を交換する必要があることです。`UTF-32` はこの問題を回避します: バイト順は、常に自然なエンディアンに従います。しかし、これらのバイト順が異なるエンディアン性を持つ CPU によって読まれる場合、結局バイト順を交換しなければなりません。`UTF-16` あるいは `UTF-32` バイト列のエンディアン性を検出する目的で、いわゆる BOM (「バイト・オーダー・マーク」) があります。これは Unicode 文字 `U+FEFF` です。この文字はすべての `UTF-16` あるいは `UTF-32` バイト列の前に置くことができます。この文字のバイトが交換されたバージョン (`0xFFFE`) は、 Unicode テキストに現われてはならない不正な文字です。したがって、`UTF-16` あるいは `UTF-32` バイト列中の最初の文字が `U+FFFE` であるように見える場合、デコードの際にバイトを交換しなければなりません。不運にも文字 `U+FEFF` は `ZERO WIDTH NO-BREAK SPACE` として別の目的を持っていました: 幅を持たず、単語を分割することを許容しない文字。それは、例えばリガチャアルゴリズムにヒントを与えるために使用することができます。 Unicode 4.0 で、`ZERO WIDTH NO-BREAK SPACE` としての `U+FEFF` の使用は廃止予定になりました (この役割は `U+2060` (`WORD JOINER`) によって引き継がれました)。しかしながら、 Unicode ソフトウェアは、依然として両方の役割の `U+FEFF` を扱うことができなければなりません: BOM として、エンコードされたバイトのメモリレイアウトを決定する手段であり、一旦バイト列が文字列にデコードされたならば消えます; `ZERO WIDTH NO-BREAK SPACE` として、他の任意の文字のようにデコードされる通常の文字です。

さらにもう一つ Unicode 文字全てをエンコードできるエンコーディングがあり、UTF-8 と呼ばれています。UTF-8 は8ビットエンコーディングで、したがって UTF-8 にはバイト順の問題はありません。UTF-8 バイト列の各バイトは二つのパートから成ります。二つはマーカ(上位数ビット)とペイロードです。マーカは0ビットから4ビットの `1` の列に `0` のビットが一つ続いたものです。Unicode 文字は次のようにエンコードされます (x はペイロードを表わし、連結されると一つの Unicode 文字を表わします):

範囲 | エンコーディング
--- | ---
`U-00000000` ... `U-0000007F` | 0xxxxxxx
`U-00000080` ... `U-000007FF` | 110xxxxx 10xxxxxx
`U-00000800` ... `U-0000FFFF` | 1110xxxx 10xxxxxx 10xxxxxx
`U-00010000` ... `U-0010FFFF` | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Unicode 文字の最下位ビットとは最も右にある x のビットです。

UTF-8 は8ビットエンコーディングなので BOM は必要とせず、デコードされた Unicode 文字列中の `U+FEFF` は(たとえ最初の文字であったとしても) `ZERO WIDTH NO-BREAK SPACE` として扱われます。

外部からの情報無しには、Unicode 文字列のエンコーディングにどのエンコーディングが使われたのか信頼できる形で決定することは不可能です。どの charmap エンコーディングもどんなランダムなバイト列でもデコードできます。しかし UTF-8 ではそれは可能ではありません。任意のバイト列を許さないような構造を持っているからです。UTF-8 エンコーディングであることを検知する信頼性を向上させるために、Microsoft は Notepad プログラム用に UTF-8 の変種 (Python 2.5 では `"utf-8-sig"` と呼んでいます) を考案しました。Unicode 文字がファイルに書き込まれる前に UTF-8 でエンコードした BOM (バイト列では `0xef`, `0xbb`, `0xbf` のように見えます) が書き込まれます。このようなバイト値で charmap エンコードされたファイルが始まることはほとんどあり得ない (たとえば iso-8859-1 では

> LATIN SMALL LETTER I WITH DIAERESIS
> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
> INVERTED QUESTION MARK

のようになる)ので、`utf-8-sig` エンコーディングがバイト列から正しく推測される確率を高めます。つまりここでは BOM はバイト列を生成する際のバイト順を決定できるように使われているのではなく、エンコーディングを推測する助けになる印として使われているのです。`utf-8-sig` codec はエンコーディングの際ファイルに最初の3文字として `0xef`, `0xbb`, `0xbf` を書き込みます。デコーディングの際はファイルの先頭に現れたこれら3バイトはスキップします。UTF-8 では BOM の使用は推奨されておらず、一般的には避けるべきです。

## 7.8.3. 標準エンコーディング

Python には数多くの codec が組み込みで付属します。これらは C 言語の関数、対応付けを行うテーブルの両方で提供されています。以下のテーブルでは codec と、いくつかの良く知られている別名と、エンコーディングが使われる言語を列挙します。別名のリスト、言語のリストともしらみつぶしに網羅されているわけではありません。大文字と小文字、またはアンダースコアの代りにハイフンにしただけの綴りも有効な別名です; そのため、例えば `'utf-8'` は `'utf_8'` codec の正当な別名です。

多くの文字セットは同じ言語をサポートしています。これらの文字セットは個々の文字 (例えば、EURO SIGN がサポートされているかどうか) や、文字のコード部分への割り付けが異なります。特に欧州言語では、典型的に以下の変種が存在します:

- ISO 8859 コードセット
- Microsoft Windows コードページで、8859 コード形式から導出されているが、制御文字を追加のグラフィック文字と置き換えたもの
- IBM EBCDIC コードページ
- ASCII 互換の IBM PC コードページ

Codec | 別名 | 言語
--- | --- | ---
ascii | 646, us-ascii | 英語
big5 | big5-tw, csbig5 | 繁体字中国語
big5hkscs | big5-hkscs, hkscs | 繁体字中国語
cp037 | IBM037, IBM039 | 英語
cp424 | EBCDIC-CP-HE, IBM424 | ヘブライ語
cp437 | 437, IBM437 | 英語
cp500 | EBCDIC-CP-BE, EBCDIC-CP-CH, IBM500 | 西ヨーロッパ言語
cp720 |  | アラビア語
cp737 |  | ギリシャ語
cp775 | IBM775 | バルト沿岸国
cp850 | 850, IBM850 | 西ヨーロッパ言語
cp852 | 852, IBM852 | 中央および東ヨーロッパ
cp855 | 855, IBM855 | ブルガリア、ベラルーシ、マケドニア、ロシア、セルビア
cp856 |  | ヘブライ語
cp857 | 857, IBM857 | トルコ語
cp858 | 858, IBM858 | 西ヨーロッパ言語
cp860 | 860, IBM860 | ポルトガル語
cp861 | 861, CP-IS, IBM861 | アイスランド語
cp862 | 862, IBM862 | ヘブライ語
cp863 | 863, IBM863 | カナダ
cp864 | IBM864 | アラビア語
cp865 | 865, IBM865 | デンマーク、ノルウェー
cp866 | 866, IBM866 | ロシア語
cp869 | 869, CP-GR, IBM869 | ギリシャ語
cp874 |  | タイ語
cp875 |  | ギリシャ語
cp932 | 932, ms932, mskanji, ms-kanji | 日本語
cp949 | 949, ms949, uhc | 韓国語
cp950 | 950, ms950 | 繁体字中国語
cp1006 |  | Urdu
cp1026 | ibm1026 | トルコ語
cp1140 | ibm1140 | 西ヨーロッパ言語
cp1250 | windows-1250 | 中央および東ヨーロッパ
cp1251 | windows-1251 | ブルガリア、ベラルーシ、マケドニア、ロシア、セルビア
cp1252 | windows-1252 | 西ヨーロッパ言語
cp1253 | windows-1253 | ギリシャ語
cp1254 | windows-1254 | トルコ語
cp1255 | windows-1255 | ヘブライ語
cp1256 | windows-1256 | アラビア語
cp1257 | windows-1257 | バルト沿岸国
cp1258 | windows-1258 | ベトナム
euc_jp | eucjp, ujis, u-jis | 日本語
euc_jis_2004 | jisx0213, eucjis2004 | 日本語
euc_jisx0213 | eucjisx0213 | 日本語
euc_kr | euckr, korean, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001 | 韓国語
gb2312 | chinese, csiso58gb231280, euc- cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso- ir-58 | 簡体字中国語
gbk | 936, cp936, ms936 | Unified Chinese
gb18030 | gb18030-2000 | Unified Chinese
hz | hzgb, hz-gb, hz-gb-2312 | 簡体字中国語
iso2022_jp | csiso2022jp, iso2022jp, iso-2022-jp | 日本語
iso2022_jp_1 | iso2022jp-1, iso-2022-jp-1 | 日本語
iso2022_jp_2 | iso2022jp-2, iso-2022-jp-2 | 日本語, 韓国語, 簡体字中国語, 西欧, ギリシャ語
iso2022_jp_2004 | iso2022jp-2004, iso-2022-jp-2004 | 日本語
iso2022_jp_3 | iso2022jp-3, iso-2022-jp-3 | 日本語
iso2022_jp_ext | iso2022jp-ext, iso-2022-jp-ext | 日本語
iso2022_kr | csiso2022kr, iso2022kr, iso-2022-kr | 韓国語
latin_1 | iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1 | 西ヨーロッパ
iso8859_2 | iso-8859-2, latin2, L2 | 中央および東ヨーロッパ
iso8859_3 | iso-8859-3, latin3, L3 | エスペラント、マルタ
iso8859_4 | iso-8859-4, latin4, L4 | バルト沿岸国
iso8859_5 | iso-8859-5, cyrillic | ブルガリア、ベラルーシ、マケドニア、ロシア、セルビア
iso8859_6 | iso-8859-6, arabic | アラビア語
iso8859_7 | iso-8859-7, greek, greek8 | ギリシャ語
iso8859_8 | iso-8859-8, hebrew | ヘブライ語
iso8859_9 | iso-8859-9, latin5, L5 | トルコ語
iso8859_10 | iso-8859-10, latin6, L6 | 北欧語
iso8859_11 | iso-8859-11, thai | タイ語
iso8859_13 | iso-8859-13, latin7, L7 | バルト沿岸国
iso8859_14 | iso-8859-14, latin8, L8 | ケルト語
iso8859_15 | iso-8859-15, latin9, L9 | 西ヨーロッパ言語
iso8859_16 | iso-8859-16, latin10, L10 | 南東ヨーロッパ
johab | cp1361, ms1361 | 韓国語
koi8_r |  | ロシア語
koi8_u |  | ウクライナ語
mac_cyrillic | maccyrillic | ブルガリア、ベラルーシ、マケドニア、ロシア、セルビア
mac_greek | macgreek | ギリシャ語
mac_iceland | maciceland | アイスランド語
mac_latin2 | maclatin2, maccentraleurope | 中央および東ヨーロッパ
mac_roman | macroman | 西ヨーロッパ言語
mac_turkish | macturkish | トルコ語
ptcp154 | csptcp154, pt154, cp154, cyrillic-asian | カザフ
shift_jis | csshiftjis, shiftjis, sjis, s_jis | 日本語
shift_jis_2004 | shiftjis2004, sjis_2004, sjis2004 | 日本語
shift_jisx0213 | shiftjisx0213, sjisx0213, s_jisx0213 | 日本語
utf_32 | U32, utf32 | 全ての言語
utf_32_be | UTF-32BE | 全ての言語
utf_32_le | UTF-32LE | 全ての言語
utf_16 | U16, utf16 | 全ての言語
utf_16_be | UTF-16BE | 全ての言語 (BMP のみ)
utf_16_le | UTF-16LE | 全ての言語 (BMP のみ)
utf_7 | U7, unicode-1-1-utf-7 | 全ての言語
utf_8 | U8, UTF, utf8 | 全ての言語
utf_8_sig |  | 全ての言語

## 7.8.4. Python 特有のエンコーディング

予め定義された codec のいくつかは Python 特有のものなので、それらの codec 名は Python の外では無意味なものとなります。以下に、想定されている入出力のタイプに基づいて、それらを表にしました（テキストエンコーディングは codec の最も一般的な使用例ですが、その根底にある codec 基盤は、ただのテキストエンコーディングというよりも、任意のデータの変換をサポートしていることに注意してください）。非対称的な codec については、その目的がエンコーディングの方向を説明しています。

以下の codec では Unicode から文字列へのエンコーディング [1] 、文字列から Unicode へのデコーディング [2] を、Unicode テキストエンコーディング同様に提供しています。

Codec | 別名 | 目的
--- | --- | ---
idna |  | RFC 3490 の実装です。 `encodings.idna` も参照してください。
mbcs | dbcs | Windows のみ: 被演算子を ANSI コードページ (CP_ACP) に従ってエンコードします
palmos |  | PalmOS 3.5 のエンコーディングです
punycode |  | RFC 3492 を実装しています。
raw_unicode_escape |  | Python ソースコードにおける raw Unicode リテラルとして適切な文字列を生成します。
rot_13 | rot13 | 被演算子のシーザー暗号 (Caesar-cypher) を返します
undefined |  | 全ての変換に対して例外を送出します。バイト列と Unicode 文字列との間で coercion (強制型変換) をおこないたくない時にシステムエンコーディングとして使うことができます。
unicode_escape |  | Python ソースコードにおける Unicode リテラルとして適切な文字列を生成します。
unicode_internal |  | 被演算子の内部表現を返します。

バージョン 2.3 で追加: `idna`, `punycode` エンコーディングの追加。

以下の codec では文字列から文字列へのエンコーディングとデコーディング [2] を提供しています。

Codec | 別名 | 目的 | エンコーダ/デコーダ
--- | --- | --- | ---
base64_codec | base64, base-64 | 被演算子をマルチラインの MIME base64 に変換します (結果は常に末尾の `'\n'` を含みます) | `base64.encodestring()`, `base64.decodestring()`
bz2_codec | bz2 | 被演算子をbz2を使って圧縮します | `bz2.compress()`, `bz2.decompress()`
hex_codec | hex | 被演算子をバイトあたり 2 桁の 16 進数の表現に変換します | `binascii.b2a_hex()`, `binascii.a2b_hex()`
quopri_codec | quopri, quoted-printable, quotedprintable | 被演算子を MIME quoted printable 形式に変換します | `quotetabs=True` を指定した `quopri.encode()`, `quopri.decode()`
string_escape |  | Python ソースコードにおける文字列リテラルとして適切な文字列を生成します。 |
uu_codec | uu | 被演算子を uuencode を用いて変換します | `uu.encode()`, `uu.decode()`
zlib_codec | zip, zlib | 被演算子を gzip を用いて圧縮します | `zlib.compress()`, `zlib.decompress()`

[1] | unicode オブジェクトを入力として受け容れる場所では str オブジェクトも許容されます。この場合デフォルトエンコーディングを使って暗黙に unicode に変換されます。この変換が失敗した場合はエンコード操作が `UnicodeDecodeError` を起こします。

[2] | (1, 2) str オブジェクトを入力として受け容れる場所では unicode オブジェクトも許容されます。この場合デフォルトエンコーディングを使って暗黙に str に変換されます。この変換が失敗した場合はデコード操作が `UnicodeEncodeError` を起こします。

## 7.8.5. `encodings.idna` --- アプリケーションにおける国際化ドメイン名 (IDNA)

バージョン 2.3 で追加.

このモジュールでは RFC 3490 (アプリケーションにおける国際化ドメイン名、 IDNA: Internationalized Domain Names in Applications) および RFC 3492 (Nameprep: 国際化ドメイン名 (IDN) のための stringprep プロファイル) を実装しています。このモジュールは `punycode` エンコーディングおよび `stringprep` の上に構築されています。

これらの RFC はともに、非 ASCII 文字の入ったドメイン名をサポートするためのプロトコルを定義しています。 (`www.Alliancefrançaise.nu` のような) 非 ASCII 文字を含むドメイン名は、 ASCII と互換性のあるエンコーディング (ACE、 `www.xn--alliancefranaise-npb.nu` のような形式) に変換されます。ドメイン名の ACE 形式は、 DNS クエリ、 HTTP Host フィールドなどといった、プロトコル中で任意の文字を使えないような全ての局面で用いられます。この変換はアプリケーション内で行われます; 可能ならユーザからは不可視となります: アプリケーションは Unicode ドメインラベルをネットワークに載せる際に IDNA に、 ACE ドメインラベルをユーザに提供する前に Unicode に、それぞれ透過的に変換しなければなりません。

Python ではこの変換をいくつかの方法でサポートします: `idna` codec は Unicode と ACE 間の変換を行い、入力文字列を RFC 3490 の section 3.1 (1) で定義されている区切り文字に基づいてラベルに分解し、各ラベルを要求通りに ACE に変換します。逆に、入力のバイト文字列を `.` 区切り文字でラベルに分解し、 ACE ラベルを Unicode に変換します。さらに、 `socket` モジュールは Unicode ホスト名を ACE に透過的に変換するため、アプリケーションはホスト名を `socket` モジュールに渡す際にホスト名の変換に煩わされることがありません。その上で、ホスト名を関数パラメタとして持つ、 `httplib` や `ftplib` のようなモジュールでは Unicode ホスト名を受理します (`httplib` でもまた、 `Host:` フィールドにある IDNA ホスト名を、フィールド全体を送信する場合に透過的に送信します)。

(逆引きなどによって) ネットワーク越しにホスト名を受信する際、Unicode への自動変換は行われません: こうしたホスト名をユーザに提供したいアプリケーションでは、Unicode にデコードしてやる必要があります。

`encodings.idna` ではまた、 nameprep 手続きを実装しています。 nameprep はホスト名に対してある正規化を行って、国際化ドメイン名で大小文字を区別しないようにするとともに、類似の文字を一元化します。 nameprep 関数は必要なら直接使うこともできます。

`encodings.idna.``nameprep`(label)

  label を nameprep したバージョンを返します。現在の実装ではクエリ文字列を仮定しているので、`AllowUnassigned` は真です。

`encodings.idna.``ToASCII`(label)

  RFC 3490 仕様に従ってラベルを ASCIIに変換します。 `UseSTD3ASCIIRules` は偽であると仮定します。

`encodings.idna.``ToUnicode`(label)

  RFC 3490 仕様に従ってラベルを Unicode に変換します。

## 7.8.6. `encodings.utf_8_sig` --- BOM 印付き UTF-8

バージョン 2.5 で追加.

このモジュールは UTF-8 codec の変種を実装します。エンコーディング時は、UTF-8 でエンコードしたバイト列の前に UTF-8 でエンコードした BOM を追加します。これは内部状態を持つエンコーダで、この動作は (バイトストリームの最初の書き込み時に) 一度だけ行なわれます。デコーディング時は、データの最初に UTF-8 でエンコードされた BOM があれば、それをスキップします。