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.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 パラメータを与えた場合、有効なデリミタ文字を含んでいるはずの文字列として解釈されます。The dialect is deduced by parsing the sample with every plausible combination of parameters and choosing the combination which splits the sample into rows with the most consistent number of fields, so the returned dialect is consistent with how
reader()will parse the sample. RaiseErrorif no combination fits the sample, in particular if it is a single column, so there is no delimiter to find.If several combinations fit the sample equally well --- for example if both
','and';'split every row consistently --- the delimiters listed in thepreferredattribute are preferred, in that order, no matter how many times each of them occurs.The lineterminator parameter is deduced separately, by a majority vote among the line endings of the sample. A tie is broken in the order
'\r\n','\n','\r', so a sample without a complete line gives'\r\n'.バージョン 3.16 で変更: The dialect is now deduced by trial parsing and the results may differ from those of earlier Python versions. The escapechar and lineterminator parameters can now be detected, and the requested delimiters are not restricted to ASCII.
- 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,
Trueis 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_MINIMAL¶
writerオブジェクトに、delimiter、quotechar、'\r'、'\n'、lineterminator に含まれる文字などの特殊文字を含むフィールドだけをクォートするよう指示します。 doublequote がFalseで escapechar が設定されている場合、quotechar はエスケープされ、その文字を理由としてフィールドがクォートされることはありません。
- csv.QUOTE_NONNUMERIC¶
writerオブジェクトに対し、全ての非数値フィールドをクオートするように指示します。readerオブジェクトに、クォーテーションで囲まれていないすべてのフィールドをfloat型に変換するよう指示します。注釈
Some numeric types, such as
bool,Fraction, orIntEnum, have a string representation that cannot be converted tofloat. They cannot be read in theQUOTE_NONNUMERICandQUOTE_STRINGSmodes.
- 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を組み合わせる場合、クォートされていない空のフィールドは許可されません。
Dialects support copy.replace(),
which returns a copy of the dialect
with the specified formatting parameters replaced.
バージョン 3.16 で変更: Added support for copy.replace().
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)
脚注