Python標準csvで改行ありエスケープありCSVを読み込む
すごく些細なことなのにつまづいてしまったのでメモ。誰かの役に立てば良いです。
入力フォーマット
CSVには改行を含めることができます。改行がある場合は要素をダブルクオート(“)で囲むのが普通です。
また、要素内にダブルクオートがある場合、ダブルクオートを2つ続けるか、バックスラッシュ(\)でエスケープするのが普通です。
入力
このようなCSVファイルを扱いたいけど、上手く行きませんでした。
name,message
Tom,"Hello, my name is \"Tom\""
Yamamoto,"こんにちは
私の名前は\"山本\"
です。"
読み込めはするけど、3行ではなく4行のデータとして扱われました。つまり改行の部分が正しく認識されません。
結論
readerの引数を正しく設定しよう(escapechar)
https://docs.python.org/ja/3/library/csv.html
のあたりの特にDialectが重要です。
https://docs.python.org/ja/3/library/csv.html#csv-fmt-params
ここも分かりやすいかも。
http://ja.pymotw.com/2/csv/#id5
doublequoteがデフォルトTrueなので、つまりエスケープは\“ではなくて""という形式を想定していることになります・・・これにひっかかった。
escapechar=’\\‘を設定することで、エスケープが正しく扱われて、上手く行きました。
例
import csv
print('ng_reader')
with open('data.csv', 'r') as f:
ng_reader = csv.DictReader(f)
for row in ng_reader:
print(row)
print('ok_reader')
with open('data.csv', 'r') as f:
ok_reader = csv.DictReader(f, escapechar='\\')
for row in ok_reader:
print(row)
実行結果
$ python main.py
ng_reader
OrderedDict([('name', 'Tom'), ('message', 'Hello, my name is \Tom\""')])
OrderedDict([('name', 'Yamamoto'), ('message', 'こんにちは\n私の名前は\山本\"')])
OrderedDict([('name', 'です。"'), ('message', None)])
ok_reader
OrderedDict([('name', 'Tom'), ('message', 'Hello, my name is "Tom"')])
OrderedDict([('name', 'Yamamoto'), ('message', 'こんにちは\n私の名前は"山本"\nです。')]
ng_readerは改行が正しく扱われていないのでdictが壊れてますね。。
ok_readerの方は大丈夫です。
以上です。