csv --- CSV ファイルの読み書き

ソースコード: Lib/csv.py


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

csv モジュールは、表形式のデータを CSV 形式で読み書きするクラスを実装しています。 Excel が使う CSV 形式の詳細を知らなくても、「このデータを Excel に適した形式で書き込む」ことや「Excel が生成したこのファイルからデータを読み込む」ことができます。 また、ほかのアプリケーションが解釈する CSV 形式を記述したり、特定の用途向けに独自の CSV 形式を定義したりすることもできます。

csv モジュールの reader オブジェクトと writer オブジェクトは、シーケンスを読み書きします。 DictReader クラスと DictWriter クラスを使えば、辞書形式でデータを読み書きすることもできます。

参考

PEP 305 - CSV File API

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

モジュールの内容

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

csv.reader(csvfile, /, dialect='excel', **fmtparams)

指定された csvfile の行を処理する reader オブジェクト を返します。 csvfile は文字列のイテラブルでなければならず、各文字列は reader に定義された CSV 形式である必要があります。 csvfile には通常、ファイルライクオブジェクトやリストを使います。 csvfile がファイルオブジェクトの場合は、newline='' を指定して開く必要があります [1]。 省略可能な dialect 引数では、特定の CSV 表現形式に固有のパラメータ群を指定できます。 Dialect クラスのサブクラスのインスタンスか、list_dialects() 関数が返す文字列のいずれかを指定できます。 その他の省略可能なキーワード引数 fmtparams を指定すると、現在の表現形式の書式パラメータを個別に上書きできます。 表現形式と書式パラメータの詳細については、表現形式と書式パラメータ 節を参照してください。

csv ファイルから読み込まれた各行は、文字列のリストとして返されます。QUOTE_NONNUMERIC フォーマットオプションが指定された場合を除き、データ型の変換が自動的に行われることはありません (このオプションが指定された場合、クォートされていないフィールドは浮動小数点数に変換されます)。

短い利用例:

>>> import csv
>>> with open('eggs.csv', newline='') as csvfile:
...     spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
...     for row in spamreader:
...         print(', '.join(row))
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam

ここで、eggs.csv の内容は次のとおりです:

Spam Spam Spam Spam Spam |Baked Beans|
Spam |Lovely Spam| |Wonderful Spam|
csv.writer(csvfile, /, dialect='excel', **fmtparams)

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

短い利用例:

import csv
with open('eggs.csv', 'w', newline='') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter=' ',
                            quotechar='|', quoting=csv.QUOTE_MINIMAL)
    spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])
    spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

これは、次の内容の eggs.csv を書き出します:

Spam Spam Spam Spam Spam |Baked Beans|
Spam |Lovely Spam| |Wonderful Spam|
csv.register_dialect(name, /, dialect='excel', **fmtparams)

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

csv.unregister_dialect(name)

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

csv.get_dialect(name)

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

csv.list_dialects()

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

csv.field_size_limit()
csv.field_size_limit(new_limit)

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

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

class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)

通常の reader のように動作しますが、個々の行の情報を dict にマップするオブジェクトを生成します。マップのキーは省略可能な fieldnames パラメータで与えられます。

fieldnames 引数は sequence です。 fieldnames を省略すると、ファイル f の最初の行の値をフィールド名として使い、その行を結果から除外します。 fieldnames を指定すると、それをフィールド名として使い、最初の行も結果に含めます。 フィールド名の決め方にかかわらず、辞書はその元の順序を保持します。

行がフィールド名より多くのフィールドを持っていた場合、残りのデータはリストに入れられて、 restkey により指定されたフィールド名 (デフォルトでは None) で保存されます。空白でない行がフィールド名よりも少ないフィールドしか持たない場合、足りない値は restval の値 (デフォルトは None ) によって埋められます。

その他の省略可能またはキーワード形式のパラメータは、ベースになっている reader インスタンスに渡されます。

fieldnames に渡された引数がイテレータの場合、 list に変換されます。

バージョン 3.6 で変更: 返される行の型は OrderedDict になりました。

バージョン 3.8 で変更: 返される行の型は dict になりました。

短い利用例:

>>> import csv
>>> with open('names.csv', newline='') as csvfile:
...     reader = csv.DictReader(csvfile)
...     for row in reader:
...         print(row['first_name'], row['last_name'])
...
Eric Idle
John Cleese

>>> print(row)
{'first_name': 'John', 'last_name': 'Cleese'}

names.csv の内容は次のとおりです:

first_name,last_name
Eric,Idle
John,Cleese
class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

通常の writer のように動作しますが、辞書を出力行にマップするオブジェクトを生成します。 fieldnames パラメータは、writerow() メソッドに渡された辞書の値がどのような順番でファイル f に書かれるかを指定するキーの sequence です。 省略可能な restval パラメータは、辞書に fieldnames のキーがない場合に書き込む値を指定します。 writerow() メソッドに渡された辞書に fieldnames には存在しないキーが含まれている場合、オプションの extrasaction パラメータによってどんな動作を行うかが指定されます。 この値がデフォルト値である 'raise' に設定されている場合、 ValueError が送出されます。 'ignore' に設定されている場合、辞書の余分な値は無視されます。 その他のパラメータはベースになっている writer インスタンスに渡されます。

DictReader クラスとは異なり、 DictWriter の fieldnames パラメータは省略可能ではありません。

fieldnames に渡された引数がイテレータの場合、 list に変換されます。

短い利用例:

import csv

with open('names.csv', 'w', newline='') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
    writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
    writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

これは、次の内容の names.csv を書き出します:

first_name,last_name
Baked,Beans
Lovely,Spam
Wonderful,Spam
class csv.Dialect

Dialect クラスはコンテナクラスです。その属性に、ダブルクォート、空白文字、デリミタなどの扱い方に関する情報を含みます。CSV には厳密な規格がないため、アプリケーションによって生成される CSV データはそれぞれ僅かに異なります。 Dialect クラスのインスタンスは reader と writer のインスタンスの挙動を定義します。

利用可能な Dialect の名前はすべて list_dialects() で取得できます。 次のように初期化関数 (__init__) を通じて、個々の reader クラスや writer クラスに表現形式を指定できます。

import csv

with open('students.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile, dialect='unix')
class csv.excel

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

class csv.excel_tab

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

class csv.unix_dialect

unix_dialect クラスは UNIX システムで生成される CSV ファイルの通常のプロパティ (行終端記号として '\n' を用い全てのフィールドをクォートするもの) を定義します。これは 'unix' という名前の dialect として登録されています。

Added in version 3.2.

class csv.Sniffer

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

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

sniff(sample, delimiters=None)

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

複数のデリミタがサンプルに同じ程度に適合する場合 (例えば、',' と ';' のどちらでもすべての行を一貫して分割できる場合)、各デリミタの出現回数にかかわらず、preferred 属性に並んだ順に優先されます。

has_header(sample)

CSV 形式であると想定したサンプルテキストを解析し、最初の行が列見出しの並びと思われる場合に True を返します。 各列を調べ、次の 2 つの主要な基準のいずれかに基づいて、サンプルに見出しが含まれるかを推定します:

  • 2番目からn番目の行は数値を含みます。

  • the second through n-th rows contain strings where at least one value's length differs from that of the putative header of that column.

Twenty-one rows after the header are sampled; if more than half of the columns + rows meet the criteria, True is returned.

注釈

このメソッドは大雑把なヒューリスティックであり、結果が偽陽性や偽陰性である可能性があります。

Sniffer クラスには以下の属性があります:

preferred

同程度に適合する候補がある場合に優先するデリミタを、優先順に並べたリストです。 変更できます。 初期値は [',', '\t', ';', ' ', ':'] です。

Sniffer の利用例:

with open('example.csv', newline='') as csvfile:
    dialect = csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    # ... ここで CSV ファイルの内容を処理します ...

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

csv.QUOTE_ALL

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

csv.QUOTE_MINIMAL

writer オブジェクトに、delimiter、quotechar、'\r'、'\n'、lineterminator に含まれる文字などの特殊文字を含むフィールドだけをクォートするよう指示します。 doublequote が False で escapechar が設定されている場合、quotechar はエスケープされ、その文字を理由としてフィールドがクォートされることはありません。

csv.QUOTE_NONNUMERIC

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

reader オブジェクトに、クォーテーションで囲まれていないすべてのフィールドを float 型に変換するよう指示します。

注釈

Some numeric types, such as bool, Fraction, or IntEnum, have a string representation that cannot be converted to float. They cannot be read in the QUOTE_NONNUMERIC and QUOTE_STRINGS modes.

csv.QUOTE_NONE

writer オブジェクトに、フィールドを一切クォートしないよう指示します。 出力データに現在の delimiter、quotechar、escapechar、'\r'、'\n'、または lineterminator に含まれる文字が現れると、その直前に現在の escapechar 文字を付けます。 escapechar が設定されていない場合、エスケープが必要な文字が見つかると writer は Error を送出します。 quotechar のエスケープを避けるには、それを None に設定してください。

reader オブジェクトに、クオート文字に対する特殊処理を行わないよう指示します。

csv.QUOTE_NOTNULL

writer オブジェクトに、None ではないすべてのフィールドをクォートするよう指示します。 QUOTE_ALL に似ていますが、フィールドの値が None の場合は、クォートされていない空文字列を書き込みます。

reader オブジェクトに、クォートされていない空のフィールドを None と解釈し、それ以外は QUOTE_ALL と同様に動作するよう指示します。

Added in version 3.12.

csv.QUOTE_STRINGS

writer オブジェクトに、文字列のフィールドを常にクォートするよう指示します。 QUOTE_NONNUMERIC に似ていますが、フィールドの値が None の場合は、クォートされていない空文字列を書き込みます。

reader オブジェクトに、クォートされていない空文字列を None と解釈し、それ以外は QUOTE_NONNUMERIC と同様に動作するよう指示します。

Added in version 3.12.

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

exception csv.Error

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

表現形式と書式パラメータ

入出力レコードの形式を簡単に指定できるように、書式パラメータを表現形式 (dialect) としてまとめています。 表現形式は Dialect クラスのサブクラスであり、CSV ファイルの形式を記述するさまざまな属性を持ちます。 reader オブジェクトや writer オブジェクトを作成する際、dialect 引数には文字列か Dialect クラスのサブクラスを指定できます。 dialect 引数に加えて、またはその代わりに、書式パラメータを個別に指定することもできます。 各パラメータの名前は、以下で定義する Dialect クラスの属性名と同じです。

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

Dialect.delimiter

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

Dialect.doublequote

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

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

Dialect.escapechar

writer がエスケープを要する以下の文字をエスケープするために使う、1 文字の文字列です:

  • quoting が QUOTE_NONE の場合は、delimiter、quotechar、'\r'、'\n'、および lineterminator に含まれる文字。

  • doublequote が False の場合は quotechar。

  • escapechar 自身。

読み込み時には、escapechar は直後の文字の特殊な意味を取り除きます。 デフォルトは None で、この場合エスケープは無効です。

バージョン 3.10 で変更: 以前は escapechar 自身がエスケープされず、読み込み時に失われていました。

バージョン 3.11 で変更: 空の escapechar は許可されていません。

Dialect.lineterminator

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

注釈

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

Dialect.quotechar

delimiter や quotechar などの特殊文字、または改行文字 ('\r'、'\n'、lineterminator に含まれる文字) を含むフィールドをクォートするための、1 文字の文字列です。 デフォルトは '"' です。 quoting が QUOTE_NONE の場合に '"' がエスケープされないようにするには、None に設定できます。

バージョン 3.11 で変更: 空の quotechar は許可されていません。

Dialect.quoting

writer がクォートを生成する条件と、reader がクォートを認識する条件を制御します。 QUOTE_* 定数 のいずれかを指定できます。 デフォルトは、quotechar が None でなければ QUOTE_MINIMAL、そうでなければ QUOTE_NONE です。

Dialect.skipinitialspace

True の場合、delimiter の直後の空白は無視されます。 デフォルトは False です。 delimiter=' ' と skipinitialspace=True を組み合わせる場合、クォートされていない空のフィールドは許可されません。

Dialect.strict

True の場合、 不正な CSV 入力に対して Error を送出します。デフォルトでは False です。

reader オブジェクト

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

csvreader.__next__()

reader の反復可能なオブジェクトから、現在の表現形式 (Dialect) に基づいて次の行を解析してリスト(オブジェクトが reader() から返された場合)または辞書 ( DictReader のインスタンスの場合)として返します。通常は next(reader) のようにして呼び出すことになります。

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

csvreader.dialect

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

csvreader.line_num

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

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

DictReader.fieldnames

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

writer オブジェクト

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

csvwriter.writerow(row, /)

現在の表現形式 (Dialect.)に沿ってフォーマットされた row パラメータを writer のファイルオブジェクトに書き込みます。ファイルオブジェクトの write メソッドを呼び出した際の戻り値を返します。

バージョン 3.5 で変更: 任意のイテラブルのサポートの追加。

csvwriter.writerows(rows, /)

rows 引数 (上で解説した row オブジェクトのイテラブル) の全ての要素を現在の表現形式に基づいて書式化し、writer のファイルオブジェクトに書き込みます。

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

csvwriter.dialect

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

DictWriter のオブジェクトは以下の public メソッドを持っています:

DictWriter.writeheader()

コンストラクタで指定したフィールド名を、現在の表現形式に従って整形し、writer のファイルオブジェクトに 1 行書き込みます。 内部で呼び出す csvwriter.writerow() の戻り値を返します。

Added in version 3.2.

バージョン 3.8 で変更: writeheader() は内部的に利用している csvwriter.writerow() メソッドの返り値を返すようになりました。

使用例

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

import csv
with open('some.csv', newline='') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

別の書式での読み込み:

import csv
with open('passwd', newline='') as f:
    reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
    for row in reader:
        print(row)

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

import csv
with open('some.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(someiterable)

CSV ファイルを読み込み用に開くには open() を使うため、デフォルトでは UTF-8 を使用してファイルを Unicode にデコードします。 別のエンコーディングでデコードするには、open() の encoding 引数を使ってください。

import csv
with open('some.csv', newline='', encoding='latin-1') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

デフォルト以外のエンコーディングで書き込む場合も同様です。 出力ファイルを開く際に encoding 引数を指定してください。

新しい表現形式の登録:

import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', newline='') as f:
    reader = csv.reader(f, 'unixpwd')

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

import csv, sys
filename = 'some.csv'
with open(filename, newline='') as f:
    reader = csv.reader(f)
    try:
        for row in reader:
            print(row)
    except csv.Error as e:
        sys.exit(f'file {filename}, line {reader.line_num}: {e}')

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

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

脚注