[解決!Python]CSVファイルに書き込みを行うには(csvモジュール編)解決!Python

pandasやNumPyを使わずに、Pythonに標準で付属するcsvモジュールを使って、CSVファイルに書き込みを行う方法を紹介する。

» 2024年02月01日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

* 本稿は2021年8月17日に公開された記事をPython 3.12.1で動作確認したものです(確認日:2024年2月1日)。


import csv

# サンプルデータとテキストファイルの内容を出力する関数の準備
header = ['name', 'age', 'tel']
isshiki = ['一色', 25, 'xxxx-yyyy']
endo = ['遠藤', 45, 'mmmm-nnnnn']
kawasaki = ['かわさき', 80, 'zzzz-aaaa']
mylist = [isshiki, endo, kawasaki]

for row in mylist:
    print(row)
# 出力結果:
#['一色', 25, 'xxxx-yyyy']
#['遠藤', 45, 'mmmm-nnnnn']
#['かわさき', 80, 'zzzz-aaaa']

from pathlib import Path
def print_lines():
    print(Path('test.csv').read_text())

# csvモジュールを使って1行の内容をCSVファイルに書き込み
with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(isshiki)

print_lines()  # 一色,25,xxxx-yyyy

# csvモジュールを使って複数行の内容をCSVファイルに書き込み
with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(mylist)

print_lines()
# 出力結果:
#一色,25,xxxx-yyyy
#遠藤,45,mmmm-nnnnn
#かわさき,80,zzzz-aaaa

# ヘッダーを行頭に書き込む
with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(header)
    writer.writerows(mylist)

print_lines()
# 出力結果:
#name,age,tel
#一色,25,xxxx-yyyy
#遠藤,45,mmmm-nnnnn
#かわさき,80,zzzz-aaaa

# 区切り文字をカンマからタブに変更する
with open('test.tsv', 'w', newline='') as f:
    writer = csv.writer(f, delimiter='\t')
    writer.writerow(isshiki)

repr(Path('test.tsv').read_text())  # "'一色\\t25\\txxxx-yyyy\\n'"

# 全てのフィールドを引用符で囲む(デフォルトはダブルクオート)
with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f, quoting=csv.QUOTE_ALL)
    writer.writerow(isshiki)

print_lines()  # "一色","25","xxxx-yyyy"

# 数値以外のフィールドをシングルクオートで囲む
with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC, quotechar="'")
    writer.writerow(isshiki)

print_lines()  # '一色',25,'xxxx-yyyy'

# 辞書の要素をCSVファイルに書き込む
mydict_list = [dict(zip(header, row)) for row in mylist]
for items in mydict_list:
    print(items)
# 出力結果:
#{'name': '一色', 'age': 25, 'tel': 'xxxx-yyyy'}
#{'name': '遠藤', 'age': 45, 'tel': 'mmmm-nnnnn'}
#{'name': 'かわさき', 'age': 80, 'tel': 'zzzz-aaaa'}

with open('test.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=header)
    writer.writeheader()
    writer.writerows(mydict_list)

print_lines()
# 出力結果:
#name,age,tel
#一色,25,xxxx-yyyy
#遠藤,45,mmmm-nnnnn
#かわさき,80,zzzz-aaaa


csvモジュールを使ったCSVファイルの読み込み

 Pythonにはcsvモジュールが標準で添付されている。これをインポートすることで、リストなどの内容のCSVファイルへの書き込みが行える(ただし、CSV形式のデータの読み書きをより柔軟な形で行うのであれば、pandasNumPyを使った方がよいだろう)。

 その基本的な手順は次の通り。

  1. CSVファイルを表すファイルオブジェクトを作成
  2. そのファイルオブジェクトを、csv.writer関数に渡して、writerオブジェクトを取得
  3. writerowメソッドを使って1行分のデータを、あるいはwriterowsメソッドを使って複数行分のデータをCSVファイルに書き込む

 ここでは、次のようなデータ(と、書き出したテキストファイルの内容を表示する関数)を使って、その方法を見ていくことにする。

header = ['name', 'age', 'tel']
isshiki = ['一色', 25, 'xxxx-yyyy']
endo = ['遠藤', 45, 'mmmm-nnnnn']
kawasaki = ['かわさき', 80, 'zzzz-aaaa']
mylist = [isshiki, endo, kawasaki]

for row in mylist:
    print(row)
# 出力結果:
#['一色', 25, 'xxxx-yyyy']
#['遠藤', 45, 'mmmm-nnnnn']
#['かわさき', 80, 'zzzz-aaaa']

from pathlib import Path
def print_lines():
    print(Path('test.csv').read_text())


 上で紹介した手順で1行分のデータをCSVファイルに書き込む簡単な例を以下に示す。

import csv

with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(isshiki)

print_lines()  # 一色,25,xxxx-yyyy


 この例では、test.csvファイルを書き込みモードでオープンし、そのファイルオブジェクトをcsv.writer関数に渡して、writerオブジェクトを取得している。次に、writerowメソッドを使って、リストの要素をCSVファイルへ書き込んでいる。writerオブジェクトは、与えられたデータを区切り文字で区切った文字列に変換して、ファイルに書き込みを行う。

 open関数のnewline引数には空文字列を渡しているが、これは行末コードの変換を行わないことを意味している。これはCSVファイルのフィールド要素に改行文字が含まれている場合に、それらを適切に解釈できるようにするためのものだ(csv.writer関数の説明でそうすることが推奨されている)。

 print_lines関数の出力結果を見ると、リストの要素がカンマ区切りで分割されて書き込まれていることが分かる。

 複数行のデータをまとめてCSVファイルに書き込むにはwriterowsメソッドを使用する。以下に例を示す。

with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(mylist)

print_lines()
# 出力結果:
#一色,25,xxxx-yyyy
#遠藤,45,mmmm-nnnnn
#かわさき,80,zzzz-aaaa


 ここでは、writerowsメソッドにリストを要素とするリスト(リストのリスト)を渡している。これにより、名前/年齢/電話番号を格納しているリストが1行分のデータとして書き込まれ、全体としては3行分のデータの書き込みが行われている。

 CSVファイルにヘッダー行が必要であれば、データを書き込む前に別途ヘッダーを書き込めばよい。以下に例を示す。

with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(header)
    writer.writerows(mylist)

print_lines()
# 出力結果:
#name,age,tel
#一色,25,xxxx-yyyy
#遠藤,45,mmmm-nnnnn
#かわさき,80,zzzz-aaaa


 辞書の内容をCSVファイルに書き込む場合には、DictWriterオブジェクトの作成時にfieldnames引数にヘッダー情報を与えた上で、writeheaderメソッドを使ってもよい(後述)。

区切り文字をカンマからタブに変更する

 上で見たように、csv.writer関数によって得られるwriterオブジェクトはデフォルトでリストなどの反復可能オブジェクトの要素をカンマで区切って、ファイルに書き出す。区切り文字を変更したいのであれば、csv.writer関数の呼び出し時にdelimiter引数に区切り文字を渡してやる。例えば、以下はタブを区切り文字にする例だ。

with open('test.tsv', 'w', newline='') as f:
    writer = csv.writer(f, delimiter='\t')
    writer.writerow(isshiki)

repr(Path('test.tsv').read_text())  # "'一色\\t25\\txxxx-yyyy\\n'"


 テキストを読み込んで、repr関数でその表現を確認すると、カンマの区切りにタブ文字が使われているのが確認できた。タブ区切りのデータを読み込む際には、もちろん区切り文字を指定する必要がある点には注意。

with open('test.tsv', newline='') as f:
    reader = csv.reader(f, delimiter='\t')
    for row in reader:
        print(row)  # ['一色', '25', 'xxxx-yyyy']


フィールドを引用符で囲む

 CSVの書き込みを行う際には、各フィールドを引用符で囲むこともできる。デフォルトでは、あるフィールドの値として区切り文字が含まれている場合などに引用符で囲まれるようになっている。

tmp = ['1, 2, 3', '4, 5, 6']
with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(tmp)

print_lines()  # "1, 2, 3","4, 5, 6"


 例えば、このコードでは文字列リストの要素に(デフォルトの区切り文字である)カンマが含まれている。そのため、文字列要素をダブルクオートで囲んだものをカンマで区切って書き出している。

 csv.writer関数の呼び出し時には、quoting引数に引用符の使い方(引用符で囲む/囲まない/特定のフィールドだけを囲むなど)を指定できる。指定できるのは以下の値だ。

  • csv.QUOTE_ALL:全てのフィールドを引用符で囲む
  • csv.QUOTE_MINIMAL:フィールドの値に特別な文字(区切り文字、引用符、改行文字など)が含まれている場合にのみ引用符で囲む(デフォルト値)
  • csv.QUOTE_NONNUMERIC:数値以外のフィールドは全て引用符で囲む
  • csv.QUOTE_NONE:全てのフィールドを引用符で囲まない

 以下に例を示す。

with open('test.csv', 'w', newline='') as f:
    writer = csv.writer(f, quoting=csv.QUOTE_ALL)
    writer.writerow(isshiki)

print_lines()  # "一色","25","xxxx-yyyy"


 この例では、全てのフィールドを引用符で囲むように指定しているので、テキストファイルの内容を見ると、全てが(デフォルトの引用符である)ダブルクオートで囲まれている。

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。