13.1。 csv —CSVファイルの読み取りと書き込み
バージョン2.3の新機能。
いわゆるCSV(コンマ区切り値)形式は、スプレッドシートおよびデータベースの最も一般的なインポートおよびエクスポート形式です。 「CSV標準」がないため、フォーマットは、それを読み書きする多くのアプリケーションによって操作上定義されます。 標準がないということは、さまざまなアプリケーションで生成および消費されるデータに微妙な違いが存在することが多いことを意味します。 これらの違いにより、複数のソースからのCSVファイルを処理するのが面倒になる可能性があります。 それでも、区切り文字と引用文字は異なりますが、全体的な形式は十分に類似しているため、そのようなデータを効率的に操作できる単一のモジュールを記述して、プログラマーからのデータの読み取りと書き込みの詳細を隠すことができます。
csv モジュールは、CSV形式で表形式のデータを読み書きするためのクラスを実装します。 これにより、プログラマーは、Excelで使用されるCSV形式の正確な詳細を知らなくても、「このデータをExcelで推奨される形式で書き込む」または「Excelで生成されたこのファイルからデータを読み取る」と言うことができます。 プログラマーは、他のアプリケーションが理解できるCSV形式を記述したり、独自の専用CSV形式を定義したりすることもできます。
csv モジュールの reader および writer オブジェクトは、シーケンスの読み取りと書き込みを行います。 プログラマーは、 DictReader および DictWriter クラスを使用して、辞書形式でデータを読み書きすることもできます。
ノート
このバージョンの csv モジュールは、Unicode入力をサポートしていません。 また、現在、ASCIINUL文字に関していくつかの問題があります。 したがって、安全のために、すべての入力はUTF-8または印刷可能なASCIIである必要があります。 セクション例の例を参照してください。
13.1.1。 モジュールの内容
csv モジュールは、次の関数を定義します。
- csv.reader(csvfile, dialect='excel', **fmtparams)
指定された csvfile の行を反復処理するリーダーオブジェクトを返します。 csvfile は、 iterator プロトコルをサポートし、
next()
メソッドが呼び出されるたびに文字列を返す任意のオブジェクトにすることができます。ファイルオブジェクトとリストオブジェクトの両方が適しています。 csvfile がファイルオブジェクトの場合、違いが生じるプラットフォームでは「b」フラグを付けて開く必要があります。 オプションの dialect パラメーターを指定できます。これは、特定のCSV方言に固有のパラメーターのセットを定義するために使用されます。 これは、 Dialect クラスのサブクラスのインスタンス、または list_dialects()関数によって返される文字列の1つである可能性があります。 他のオプションの fmtparams キーワード引数を指定して、現在の方言の個々のフォーマットパラメーターをオーバーライドできます。 方言とフォーマットパラメータの詳細については、セクション方言とフォーマットパラメータを参照してください。csvファイルから読み取られた各行は、文字列のリストとして返されます。 自動データ型変換は実行されません。
簡単な使用例:
>>> import csv >>> with open('eggs.csv', 'rb') 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
バージョン2.5で変更:パーサーは、複数行の引用符で囲まれたフィールドに関してより厳密になりました。 以前は、改行文字を終了せずに引用符で囲まれたフィールド内で行が終了した場合、返されたフィールドに改行が挿入されていました。 この動作により、フィールド内にキャリッジリターン文字を含むファイルを読み取るときに問題が発生しました。 改行を挿入せずにフィールドを返すように動作が変更されました。 結果として、フィールド内に埋め込まれた改行が重要である場合、入力は改行文字を保持する方法で行に分割する必要があります。
- csv.writer(csvfile, dialect='excel', **fmtparams)
指定されたファイルのようなオブジェクトで、ユーザーのデータを区切り文字列に変換するライターオブジェクトを返します。 csvfile は、
write()
メソッドを持つ任意のオブジェクトにすることができます。 csvfile がファイルオブジェクトの場合、違いが生じるプラットフォームでは「b」フラグを付けて開く必要があります。 オプションの dialect パラメーターを指定できます。これは、特定のCSV方言に固有のパラメーターのセットを定義するために使用されます。 これは、 Dialect クラスのサブクラスのインスタンス、または list_dialects()関数によって返される文字列の1つである可能性があります。 他のオプションの fmtparams キーワード引数を指定して、現在の方言の個々のフォーマットパラメーターをオーバーライドできます。 方言とフォーマットパラメータの詳細については、セクション方言とフォーマットパラメータを参照してください。 DB APIを実装するモジュールとのインターフェースをできるだけ簡単にするために、値 None は空の文字列として書き込まれます。 これは可逆的な変換ではありませんが、cursor.fetch*
呼び出しから返されたデータを前処理することなく、SQLNULLデータ値をCSVファイルに簡単にダンプできます。 フロートは、書き込まれる前に repr()で文字列化されます。 他のすべての非文字列データは、書き込まれる前に str()で文字列化されます。簡単な使用例:
import csv with open('eggs.csv', 'wb') 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'])
- csv.register_dialect(name, [dialect, ]**fmtparams)
- 方言を名前に関連付けます。 name は文字列またはUnicodeオブジェクトである必要があります。 方言は、 Dialect のサブクラスを渡すか、 fmtparams キーワード引数、またはその両方で指定できます。キーワード引数は、方言のパラメーターをオーバーライドします。 方言とフォーマットパラメータの詳細については、セクション方言とフォーマットパラメータを参照してください。
- 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(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)
通常のリーダーのように動作するが、読み取られた情報を、オプションの fieldnames パラメーターによってキーが指定されるdictにマップするオブジェクトを作成します。 fieldnames パラメーターは、 sequence であり、その要素は入力データのフィールドに順番に関連付けられています。 これらの要素は、結果の辞書のキーになります。 fieldnames パラメーターを省略すると、ファイル f の最初の行の値がフィールド名として使用されます。 読み取られた行にfieldnamesシーケンスよりも多くのフィールドがある場合、残りのデータは restkey の値でキー設定されたシーケンスとして追加されます。 読み取られた行のフィールドがfieldnamesシーケンスよりも少ない場合、残りのキーはオプションの restval パラメーターの値を取ります。 その他のオプションまたはキーワード引数は、基になる reader インスタンスに渡されます。
簡単な使用例:
>>> import csv >>> with open('names.csv') as csvfile: ... reader = csv.DictReader(csvfile) ... for row in reader: ... print(row['first_name'], row['last_name']) ... Baked Beans Lovely Spam Wonderful Spam
- class csv.DictWriter(f, fieldnames, restval=, extrasaction='raise', dialect='excel', *args, **kwds)
通常のライターのように動作するが、辞書を出力行にマップするオブジェクトを作成します。 fieldnames パラメーターは、
writerow()
メソッドに渡されたディクショナリ内の値がファイル f [に書き込まれる順序を識別するキーのシーケンスです。 X183X]。 オプションの restval パラメーターは、辞書に fieldnames のキーがない場合に書き込まれる値を指定します。writerow()
メソッドに渡されたディクショナリにフィールド名にないキーが含まれている場合、オプションの extrasaction パラメータは実行するアクションを示します。'raise'
に設定すると、ValueError
が発生します。'ignore'
に設定されている場合、ディクショナリ内の余分な値は無視されます。 その他のオプションまたはキーワード引数は、基になる writer インスタンスに渡されます。DictReader クラスとは異なり、 DictWriter の fieldnames パラメーターはオプションではないことに注意してください。 Pythonの dict オブジェクトは順序付けられていないため、ファイル f に行を書き込む順序を推測するのに十分な情報がありません。
簡単な使用例:
import csv with open('names.csv', 'w') 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'})
- class csv.excel
- excel クラスは、Excelで生成されたCSVファイルの通常のプロパティを定義します。 方言名
'excel'
で登録されています。
- class csv.excel_tab
- excel_tab クラスは、Excelで生成されたTAB区切りファイルの通常のプロパティを定義します。 方言名
'excel-tab'
で登録されています。
- class csv.Sniffer
Sniffer クラスは、CSVファイルの形式を推測するために使用されます。
Sniffer クラスは、次の2つのメソッドを提供します。
- sniff(sample, delimiters=None)
指定されたサンプルを分析し、見つかったパラメーターを反映する方言サブクラスを返します。 オプションの delimiters パラメーターを指定すると、有効な区切り文字の可能性がある文字列として解釈されます。
- has_header(sample)
サンプルテキスト(CSV形式と推定)を分析し、最初の行が一連の列ヘッダーであると思われる場合は True を返します。
Sniffer の使用例:
with open('example.csv', 'rb') as csvfile:
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 オブジェクトに、数値以外のすべてのフィールドを引用するように指示します。
引用符で囲まれていないすべてのフィールドをタイプ float に変換するようにリーダーに指示します。
- csv.QUOTE_NONE
writer オブジェクトにフィールドを引用しないように指示します。 現在の区切り文字が出力データで発生する場合、その前に現在のエスケープ文字文字が付きます。 escapechar が設定されていない場合、エスケープが必要な文字が検出されると、ライターは Error を発生させます。
reader に引用符の特別な処理を実行しないように指示します。
csv モジュールは、次の例外を定義します。
- exception csv.Error
- エラーが検出されたときに、いずれかの関数によって発生します。
13.1.2。 方言とフォーマットパラメータ
入力レコードと出力レコードの形式を簡単に指定できるように、特定の形式パラメーターが方言にグループ化されています。 方言は、 Dialect クラスのサブクラスであり、特定のメソッドのセットと単一のvalidate()
メソッドがあります。 reader または writer オブジェクトを作成する場合、プログラマーは Dialect クラスの文字列またはサブクラスを方言パラメーターとして指定できます。 dialect パラメーターに加えて、またはその代わりに、プログラマーは、 Dialect クラスに対して以下で定義されている属性と同じ名前を持つ個々のフォーマットパラメーターを指定することもできます。
方言は次の属性をサポートします。
- Dialect.delimiter
- フィールドを区切るために使用される1文字の文字列。 デフォルトは
','
です。
- Dialect.doublequote
フィールド内に表示される quotechar のインスタンス自体を引用する方法を制御します。 True の場合、文字は2倍になります。 False の場合、 escapechar が quotechar のプレフィックスとして使用されます。 デフォルトは True です。
出力時に、 doublequote が False であり、 escapechar が設定されていない場合、 quotechar がフィールドで見つかりました。
- Dialect.escapechar
- quoted が QUOTE_NONE に設定されている場合、区切り文字をエスケープするためにライターが使用する1文字の文字列。の場合、 quotechar 。二重引用符は False です。 読むと、 escapechar は、次の文字から特別な意味を削除します。 デフォルトは None で、エスケープを無効にします。
- Dialect.lineterminator
writer によって生成された行を終了するために使用される文字列。 デフォルトは
'\r\n'
です。ノート
リーダーは、
'\r'
または'\n'
のいずれかを行末として認識するようにハードコードされており、改行子を無視します。 この動作は将来変更される可能性があります。
- Dialect.quotechar
- 区切り文字や quotechar などの特殊文字を含むフィールド、または改行文字を含むフィールドを引用するために使用される1文字の文字列。 デフォルトは
'"'
です。
- Dialect.quoting
- 引用符がライターによって生成され、リーダーによって認識されるタイミングを制御します。
QUOTE_*
定数のいずれかを取ることができ(セクションモジュールの内容を参照)、デフォルトは QUOTE_MINIMAL です。
- Dialect.strict
True
の場合、不正なCSV入力で例外エラーを発生させます。 デフォルトはFalse
です。
13.1.3。 リーダーオブジェクト
リーダーオブジェクト( DictReader インスタンスおよび reader()関数によって返されるオブジェクト)には、次のパブリックメソッドがあります。
- csvreader.next()
- リーダーの反復可能なオブジェクトの次の行を、現在の方言に従って解析されたリストとして返します。
リーダーオブジェクトには、次のパブリック属性があります。
- csvreader.dialect
- パーサーが使用している方言の読み取り専用の説明。
- csvreader.line_num
ソースイテレータから読み取られた行数。 レコードは複数の行にまたがることができるため、これは返されるレコードの数と同じではありません。
バージョン2.5の新機能。
DictReaderオブジェクトには、次のパブリック属性があります。
- csvreader.fieldnames
オブジェクトの作成時にパラメーターとして渡されない場合、この属性は、最初のアクセス時、または最初のレコードがファイルから読み取られるときに初期化されます。
バージョン2.6で変更されました。
13.1.4。 ライターオブジェクト
Writer
オブジェクト( DictWriter インスタンスおよび writer()関数によって返されるオブジェクト)には、次のパブリックメソッドがあります。 row は、Writer
オブジェクトの文字列または数値のシーケンスであり、フィールド名を文字列または数値にマッピングする辞書である必要があります(最初に str()を介して渡すことにより) DictWriter オブジェクト。 複素数は、parensで囲まれて書き出されることに注意してください。 これにより、CSVファイルを読み取る他のプログラムで問題が発生する可能性があります(複素数をサポートしていると仮定した場合)。
- csvwriter.writerow(row)
- row パラメーターを、現在の方言に従ってフォーマットされたライターのファイルオブジェクトに書き込みます。
- csvwriter.writerows(rows)
- rows (上記の row オブジェクトの反復可能)内のすべての要素を、現在の方言に従ってフォーマットされたライターのファイルオブジェクトに書き込みます。
ライターオブジェクトには、次のパブリック属性があります。
- csvwriter.dialect
- ライターが使用している方言の読み取り専用の説明。
DictWriterオブジェクトには、次のパブリックメソッドがあります。
- DictWriter.writeheader()
(コンストラクターで指定された)フィールド名を使用して行を記述します。
バージョン2.7の新機能。
13.1.5。 例
CSVファイルを読み取る最も簡単な例:
import csv
with open('some.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
print row
別の形式でファイルを読み取る:
import csv
with open('passwd', 'rb') as f:
reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
for row in reader:
print row
対応する最も単純な書き込み例は次のとおりです。
import csv
with open('some.csv', 'wb') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
新しい方言の登録:
import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', 'rb') as f:
reader = csv.reader(f, 'unixpwd')
リーダーのもう少し高度な使用法—エラーのキャッチと報告:
import csv, sys
filename = 'some.csv'
with open(filename, 'rb') as f:
reader = csv.reader(f)
try:
for row in reader:
print row
except csv.Error as 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の読み取りと書き込みを直接サポートしていませんが、ASCIINUL文字に関するいくつかの問題を除いて8ビットクリーンです。 したがって、NULを使用するUTF-16のようなエンコーディングを回避する限り、エンコーディングとデコーディングを処理する関数またはクラスを作成できます。 UTF-8をお勧めします。
以下のunicode_csv_reader()
は、 csv.reader をラップしてUnicodeCSVデータ(Unicode文字列のリスト)を処理するジェネレーターです。 utf_8_encoder()
は、Unicode文字列を一度に1つの文字列(または行)でUTF-8としてエンコードするジェネレーターです。 エンコードされた文字列はCSVリーダーによって解析され、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 パラメーターを受け取り、データが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)