### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python 2.6ja2 documentation »
- Python 標準ライブラリ »
- 13. ファイルフォーマット »

# 13.1. `csv` — CSV ファイルの読み書き

バージョン 2.3 で追加.

CSV (Comma Separated Values、カンマ区切り値列) と呼ばれる形式は、スプレッドシートやデータベース間でのデータのインポートやエクスポートにおける最も一般的な形式です。”CSV 標準” は存在しないため、 CSV 形式はデータを読み書きする多くのアプリケーション上の操作に応じて定義されているにすぎません。標準がないということは、異なるアプリケーションによって生成されたり取り込まれたりするデータ間では、しばしば微妙な違いが発生するということを意味します。こうした違いのために、複数のデータ源から得られた CSV ファイルを処理する作業が鬱陶しいものになることがあります。とはいえ、デリミタ (delimiter) やクオート文字の相違はあっても、全体的な形式は十分似通っているため、こうしたデータを効率的に操作し、データの読み書きにおける細々としたことをプログラマから隠蔽するような単一のモジュールを書くことは可能です。

`csv` モジュールでは、CSV 形式で書かれたテーブル状のデータを読み書きするためのクラスを実装しています。このモジュールを使うことで、プログラマは Excel で使われている CSV 形式に関して詳しい知識をもっていなくても、 “このデータを Excel で推奨されている形式で書いてください” とか、 “データを Excel で作成されたこのファイルから読み出してください” と言うことができます。プログラマはまた、他のアプリケーションが解釈できる CSV 形式を記述したり、独自の特殊な目的をもった CSV 形式を定義することができます。

`csv` モジュールの `reader` および `writer` オブジェクトはシーケンス型を読み書きします。プログラマは `DictReader` や `DictWriter` クラスを使うことで、データを辞書形式で読み書きすることもできます。

ノート

このバージョンの `csv` モジュールは Unicode 入力をサポートしていません。また、現在のところ、 ASCII NUL 文字に関連したいくつかの問題があります。従って、安全を期すには、全ての入力を UTF-8 または印字可能な ASCII にしなければなりません。これについては 使用例 節の例を参照してください。これらの制限は将来取り去られることになっています。

参考

PEP 305 - CSV File API
  Python へのこのモジュールの追加を提案している Python 改良案 (PEP: Python Enhancement Proposal)

## 13.1.1. モジュールの内容

`csv` モジュールでは以下の関数を定義しています:

`csv.``reader`(csvfile[, dialect='excel'][, fmtparam])

  与えられた csvfile 内の行を反復処理するような reader オブジェクトを返します。 csvfile はイテレータ(iterator)プロトコルをサポートし、 `next()` メソッドが呼ばれた際に常に文字列を返すような任意のオブジェクトにすることができます — ファイルオブジェクトでもリストでも構いません。 csvfile がファイルオブジェクトの場合、ファイルオブジェクトの形式に違いがあるようなプラットフォームでは ‘b’ フラグを付けて開かなければなりません。オプションとして dialect パラメタを与えることができ、特定の CSV 表現形式 (dialect) 特有のパラメタの集合を定義するために使われます。 dialect パラメタは `Dialect` クラスのサブクラスのインスタンスか、 `list_dialects()` 関数が返す文字列の一つにすることができます。別のオプションである fmtparam キーワード引数は、現在の表現形式における個々の書式パラメタを上書きするために与えることができます。表現形式および書式化パラメタの詳細については、 Dialect クラスと書式化パラメタ 節を参照してください。

  csv ファイルから読み込まれた各行は、文字列のリストとして返されます。データ型の変換が自動的に行われることはありません。

  短い利用例:

      >>> import csv
      >>> spamReader = csv.reader(open('eggs.csv', 'rb'), delimiter=' ', quotechar='|')
      >>> for row in spamReader:
      ...     print ', '.join(row)
      Spam, Spam, Spam, Spam, Spam, Baked Beans
      Spam, Lovely Spam, Wonderful Spam

  バージョン 2.5 で変更: パーサが複数行に亘るクオートされたフィールドに関して厳格になりました。以前は、クオートされたフィールドの中で終端の改行文字無しに行が終わった場合、 返されるフィールドには改行が挿入されていましたが、この振る舞いはフィールドの中に復帰文字を含むようなファイルを読むときに問題を起こしていました。 そこでフィールドに改行文字を挿入せずに返すように改められました。この結果、フィールドに埋め込まれた改行文字が重要ならば、入力は改行文字を保存する ような仕方で複数行に分割されなければなりません。 .

`csv.``writer`(csvfile[, dialect='excel'][, fmtparam])

  ユーザが与えたデータをデリミタで区切られた文字列に変換し、与えられたファイルオブジェクトに書き込むための writer オブジェクトを返します。 csvfile は `write()` メソッドを持つ任意のオブジェクトです。 csvfile がファイルオブジェクトの場合、 ‘b’ フラグが意味を持つプラットフォームでは ‘b’ フラグを付けて開かなければなりません。オプションとして dialect 引数を与えることができ、利用するCSV表現形式(dialect)を指定することができます。 dialect パラメタは `Dialect` クラスのサブクラスのインスタンスか、 `list_dialects()` 関数が返す文字列の1つにすることができます。別のオプション引数である fmtparam キーワード引数は、現在の表現形式における個々の書式パラメタを上書きするために与えることができます。 dialect と書式パラメタについての詳細は、 Dialect クラスと書式化パラメタ 節を参照してください。 DB API を実装するモジュールとのインタフェースを可能な限り容易にするために、 `None` は空文字列として書き込まれます。この処理は可逆な変換ではありませんが、SQL で NULL データ値を CSV にダンプする処理を、 `cursor.fetch*` 呼び出しによって返されたデータを前処理することなく簡単に行うことができます。他の非文字列データは、書き出される前に `str()` を使って文字列に変換されます。

  短い利用例:

      >>> import csv
      >>> spamWriter = csv.writer(open('eggs.csv', 'wb'), delimiter=' ',
      ...                         quotechar='|', quoting=csv.QUOTE_MINIMAL)
      >>> spamWriter.writerow(['Spam'] * 5 + ['Baked Beans'])
      >>> spamWriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

`csv.``register_dialect`(name[, dialect][, fmtparam])

  dialect を name と関連付けます。 name は文字列か Unicode オブジェクトでなければなりません。表現形式(dialect)は `Dialect` のサブクラスを渡すか、またはキーワード引数 fmtparam 、もしくは両方で指定できますが、キーワード引数の方が優先されます。表現形式と書式化パラメタについての詳細は、 Dialect クラスと書式化パラメタ 節を参照してください。

`csv.``unregister_dialect`(name)

  name に関連づけられた表現形式を表現形式レジストリから削除します。 name が表現形式名でない場合には `Error` を送出します。

`csv.``get_dialect`(name)

  name に関連づけられた表現形式を返します。 name が表現形式名でない場合には `Error` を送出します。

  バージョン 2.5 で変更.

`csv.``list_dialects`()

  登録されている全ての表現形式を返します。

`csv.``field_size_limit`([new_limit])

  パーサが許容する現在の最大フィールドサイズを返します。 new_limit が渡されたときは、その値が新しい上限になります。

  バージョン 2.5 で追加.

`csv` モジュールでは以下のクラスを定義しています:

class `csv.``DictReader`(csvfile[, fieldnames=None[, restkey=None[, restval=None[, dialect='excel'[, *args, **kwds]]]]])

  省略可能な fieldnames パラメタで与えられたキーを読み出された情報に対応付ける他は正規の reader のように動作するオブジェクトを生成します。 fieldnames パラメタが無い場合には、 csvfile の最初の行の値がフィールド名として利用されます。読み出された行が fieldnames のシーケンスよりも多くのフィールドを持っていた場合、残りのフィールドデータは restkey の値をキーとするシーケンスに追加されます。読み出された行が fieldnames のシーケンスよりも少ないフィールドしか持たない場合、残りのキーはオプションの restval パラメタに指定された値を取ります。その他の省略可能またはキーワード形式のパラメタはベースになっている `reader` のインスタンスに渡されます。

class `csv.``DictWriter`(csvfile, fieldnames[, restval=''[, extrasaction='raise'[, dialect='excel'[, *args, **kwds]]]])

  辞書を出力行に対応付ける他は正規の writer のように動作するオブジェクトを生成します。 fieldnames パラメタには、辞書中の `writerow()` メソッドに渡される値がどの順番で csvfile に書き出されるかを指定します。オプションの restval パラメタは、 fieldnames 内のキーが辞書中にない場合に書き出される値を指定します。 `writerow()` メソッドに渡された辞書に、 fieldnames 内には存在しないキーが入っている場合、オプションの extraaction パラメタでどのような動作を行うかを指定します。この値が `'raise'` に設定されている場合 `ValueError` が送出されます。 `'ignore'` に設定されている場合、辞書の余分の値は無視されます。その他のパラメタはベースになっている `writer` のインスタンスに渡されます。

  `DictReader` クラスとは違い、 `DictWriter` の fieldnames パラメータは省略可能ではありません。Pythonの `dict` オブジェクトは整列されていないので、列が csvfile に書かれるべき順序を推定するための十分な情報はありません。

class `csv.``Dialect`

  `Dialect` クラスはコンテナクラスで、基本的な用途としては、その属性を特定の `reader` や `writer` インスタンスのパラメタを定義するために用います。

class `csv.``excel`

  `excel` クラスは Excel で生成される CSV ファイルの通常のプロパティを定義します。これは `'excel'` という名前の dialect として登録されています。

class `csv.``excel_tab`

  `excel` クラスは Excel で生成されるタブ分割ファイルの通常のプロパティを定義します。これは `'excel-tab'` という名前の dialect として登録されています。

class `csv.``Sniffer`([sample=16384])

  `Sniffer` クラスは CSV ファイルの書式を推理するために用いられるクラスです。

  `Sniffer` クラスではメソッドを二つ提供しています:

  `sniff`(sample[, delimiters=None])

    与えられた sample を解析し、発見されたパラメタを反映した `Dialect` サブクラスを返します。オプションの delimiters パラメタを与えた場合、有効なデリミタ文字を含んでいるはずの文字列として解釈されます。

  `has_header`(sample)

    (CSV 形式と仮定される) サンプルテキストを解析して、最初の行がカラムヘッダの羅列のように推察される場合 `True` を返します。

`Sniffer` の利用例:

    csvfile = open("example.csv", "rb")
    dialect = csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    # ... process CSV file contents here ...

`csv` モジュールでは以下の定数を定義しています:

`csv.``QUOTE_ALL`

  `writer` オブジェクトに対し、全てのフィールドをクオートするように指示します。

`csv.``QUOTE_MINIMAL`

  `writer` オブジェクトに対し、 delimiter 、 quotechar または lineterminator に含まれる任意の文字のような特別な文字を含むフィールドだけをクオートするように指示します。

`csv.``QUOTE_NONNUMERIC`

  `writer` オブジェクトに対し、全ての非数値フィールドをクオートするように指示します。

  `reader` に対しては、クオートされていない全てのフィールドを float 型に変換するよう指示します。

`csv.``QUOTE_NONE`

  `writer` オブジェクトに対し、フィールドを決してクオートしないように指示します。現在の delimiter が出力データ中に現れた場合、現在設定されている escapechar 文字が前に付けられます。 escapechar がセットされていない場合、エスケープが必要な文字に遭遇した writer は `Error` を送出します。

  `reader` に対しては、クオート文字の特別扱いをしないように指示します。

`csv` モジュールでは以下の例外を定義しています:

exception `csv.``Error`

  全ての関数において、エラーが検出された際に送出される例外です。

## 13.1.2. Dialect クラスと書式化パラメタ

レコードに対する入出力形式の指定をより簡単にするために、特定の書式化パラメタは表現形式 (dialect) にまとめてグループ化されます。表現形式は `Dialect` クラスのサブクラスで、様々なクラス特有のメソッドと、 `validate()` メソッドを一つ持っています。 `reader` または `writer` オブジェクトを生成するとき、プログラマは文字列または `Dialect` クラスのサブクラスを表現形式パラメタとして渡さなければなりません。さらに、 dialect パラメタの代りに、プログラマは上で定義されている属性と同じ名前を持つ個々の書式化パラメタを `Dialect` クラスに指定することができます。

Dialect は以下の属性をサポートしています:

`Dialect.``delimiter`

  フィールド間を分割するのに用いられる 1 文字からなる文字列です。デフォルトでは `','` です。

`Dialect.``doublequote`

  フィールド内に現れた quotechar のインスタンスで、クオートではないその文字自身でなければならない文字をどのようにクオートするかを制御します。 `True` の場合、この文字は二重化されます。 `False` の場合、 escapechar は quotechar の前に置かれます。デフォルトでは `True` です。

  出力においては、 doublequote が `False` で escapechar がセットされていない場合、フィールド内に quotechar が現れると `Error` が送出されます。

`Dialect.``escapechar`

  writer が、 quoting が `QUOTE_NONE` に設定されている場合に delimiter をエスケープするため、および、 doublequote が `False` の場合に quotechar をエスケープするために用いられる、 1 文字からなる文字列です。読み込み時には escapechar はそれに引き続く文字の特別な意味を取り除きます。デフォルトでは `None` で、エスケープを行ないません。

`Dialect.``lineterminator`

  `writer` が作り出す各行を終端する際に用いられる文字列です。デフォルトでは `'\r\n'` です。

  ノート

  `reader` は `'\r'` または `'\n'` のどちらかを行末と認識するようにハードコードされており、 lineterminator を無視します。この振る舞いは将来変更されるかもしれません。

`Dialect.``quotechar`

  delimiter や quotechar といった特殊文字を含むか、改行文字を含むフィールドをクオートする際に用いられる 1 文字からなる文字列です。デフォルトでは `'"'` です。

`Dialect.``quoting`

  クオートがいつ writer によって生成されるか、また reader によって認識されるかを制御します。 `QUOTE_*` 定数のいずれか (モジュールの内容 節参照) をとることができ、デフォルトでは `QUOTE_MINIMAL` です。

`Dialect.``skipinitialspace`

  `True` の場合、 delimiter の直後に続く空白は無視されます。デフォルトでは `False` です。

## 13.1.3. reader オブジェクト

reader オブジェクト(`DictReader` インスタンス、および `reader()` 関数によって返されたオブジェクト) は、以下の public なメソッドを持っています:

`csvreader.``next`()

  reader の反復可能なオブジェクトから、現在の表現形式に基づいて次の行を解析して返します。

reader オブジェクトには以下の公開属性があります:

`csvreader.``dialect`

  パーサで使われる表現形式の読み取り専用の記述です。

`csvreader.``line_num`

  ソースイテレータから読んだ行数です。この数は返されるレコードの数とは、レコードが複数行に亘ることがあるので、一致しません。

  バージョン 2.5 で追加.

DictReader オブジェクトは、以下のpublicな属性を持っています:

`csvreader.``fieldnames`

  オブジェクトを生成するときに渡されなかった場合、この属性は最初のアクセス時か、ファイルから最初のレコードを読み出したときに初期化されます。

  バージョン 2.6 で変更.

## 13.1.4. writer オブジェクト

`Writer` オブジェクト(`DictWriter` インスタンス、および `writer()` 関数によって返されたオブジェクト) は、以下の public なメソッドを持っています:

`Writer` オブジェクト(`writer()` で生成される `DictWriter` クラスのインスタンス）は、以下の公開メソッドを持っています。 row には、 `Writer` オブジェクトの場合には文字列か数値のシーケンスを指定し、 `DictWriter` オブジェクトの場合はフィールド名をキーとして対応する文字列か数値を格納した辞書オブジェクトを指定します(数値は `str()` で変換されます)。複素数を出力する場合、値をかっこで囲んで出力します。このため、CSV ファイルを読み込むアプリケーションで（そのアプリケーションが複素数をサポートしていたとしても）問題が発生する場合があります。

`csvwriter.``writerow`(row)

  row パラメタを現在の表現形式に基づいて書式化し、 writer のファイルオブジェクトに書き込みます。

`csvwriter.``writerows`(rows)

  rows パラメタ(上記 row のリスト)全てを現在の表現形式に基づいて書式化し、 writer のファイルオブジェクトに書き込みます。

writer オブジェクトには以下の公開属性があります:

`csvwriter.``dialect`

  writer で使われる表現形式の読み取り専用の記述です。

## 13.1.5. 使用例

最も簡単な CSV ファイル読み込みの例です:

    import csv
    reader = csv.reader(file("some.csv", "rb"))
    for row in reader:
        print row

別の書式での読み込み:

    import csv
    reader = csv.reader(open("passwd", "rb"), delimiter=':', quoting=csv.QUOTE_NONE)
    for row in reader:
        print row

上に対して、単純な書き込みのプログラム例は以下のようになります。

    import csv
    writer = csv.writer(file("some.csv", "wb"))
    writer.writerows(someiterable)

新しい表現形式の登録:

    import csv

    csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)

    reader = csv.reader(open("passwd", "rb"), 'unixpwd')

もう少し手の込んだ reader の使い方 — エラーを捉えてレポートします。

    import csv, sys
    filename = "some.csv"
    reader = csv.reader(open(filename, "rb"))
    try:
        for row in reader:
            print row
    except csv.Error, e:
        sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))

このモジュールは文字列の解析は直接サポートしませんが、簡単にできます。

    import csv
    for row in csv.reader(['one,two,three']):
        print row

`csv` モジュールは直接は Unicode の読み書きをサポートしませんが、 ASCII NUL 文字に関わる問題のために8ビットクリーンに書き込みます。ですから、NUL を使う UTF-16 のようなエンコーディングを避ける限りエンコード・デコードを行なう関数やクラスを書くことができます。 UTF-8 がお勧めです。

以下の `unicode_csv_reader()` は Unicode の CSV データ (Unicode 文字列のリスト)を扱うための `csv.reader` をラップするジェネレータ(generator)です。 `utf_8_encoder()` は一度に 1 文字列(または行) ずつ Unicode 文字列を UTF-8 としてエンコードするジェネレータです。エンコードされた文字列は CSV reader により分解され、 `unicode_csv_reader()` が UTF-8 エンコードの分解された文字列をデコードして Unicode に戻します。

    import csv

    def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
        # csv.py doesn't do Unicode; encode temporarily as UTF-8:
        csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
                                dialect=dialect, **kwargs)
        for row in csv_reader:
            # decode UTF-8 back to Unicode, cell by cell:
            yield [unicode(cell, 'utf-8') for cell in row]

    def utf_8_encoder(unicode_csv_data):
        for line in unicode_csv_data:
            yield line.encode('utf-8')

その他のエンコーディングには以下の `UnicodeReader` クラスと `UnicodeWriter` クラスが使えます。二つのクラスは encoding パラメータをコンストラクタで取り、本物の reader や writer に渡されるデータが UTF-8 でエンコードされていることを保証します。

    import csv, codecs, cStringIO

    class UTF8Recoder:
        """
        Iterator that reads an encoded stream and reencodes the input to UTF-8
        """
        def __init__(self, f, encoding):
            self.reader = codecs.getreader(encoding)(f)

        def __iter__(self):
            return self

        def next(self):
            return self.reader.next().encode("utf-8")

    class UnicodeReader:
        """
        A CSV reader which will iterate over lines in the CSV file "f",
        which is encoded in the given encoding.
        """

        def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
            f = UTF8Recoder(f, encoding)
            self.reader = csv.reader(f, dialect=dialect, **kwds)

        def next(self):
            row = self.reader.next()
            return [unicode(s, "utf-8") for s in row]

        def __iter__(self):
            return self

    class UnicodeWriter:
        """
        A CSV writer which will write rows to CSV file "f",
        which is encoded in the given encoding.
        """

        def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
            # Redirect output to a queue
            self.queue = cStringIO.StringIO()
            self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
            self.stream = f
            self.encoder = codecs.getincrementalencoder(encoding)()

        def writerow(self, row):
            self.writer.writerow([s.encode("utf-8") for s in row])
            # Fetch UTF-8 output from the queue ...
            data = self.queue.getvalue()
            data = data.decode("utf-8")
            # ... and reencode it into the target encoding
            data = self.encoder.encode(data)
            # write to the target stream
            self.stream.write(data)
            # empty queue
            self.queue.truncate(0)

        def writerows(self, rows):
            for row in rows:
                self.writerow(row)

### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python 2.6ja2 documentation »
- Python 標準ライブラリ »
- 13. ファイルフォーマット »