ケースとしてはレアな気がしますが、MySQLのSELECT 〜 INTO OUTFILEで出力したCSVに対して、処理をしたい時があります。僕の場合はpythonでやるわけですが、MySQLが出力するCSVの形式がpythonデフォルトの物と違うようでハマったのでメモしておきます。
MySQLには以下のようにデータを入れておきます。JSON形式のテキストを1レコードのみ準備しています。
#!/usr/bin/python # -*- coding: utf-8 -*- import MySQLdb import simplejson as json def main(): data = ['あ', 'い', 'う'] cur = MySQLdb.connect(host='localhost', db='dbname', user='user', passwd='pass').cursor() if not cur.execute('SELECT * FROM csv_test'): cur.execute('INSERT INTO csv_test(json) VALUES(%s)', (json_data)) if __name__ == '__main__': main()
このデータをSQLでCSVに吐き出します。注意したいのはターミネータにタブを指定している事です。カンマがJSONデータに含まれている為か、後でパースする時に、デフォルトのままだと正常にパースされません。
SELECT title, json FROM csv_test LIMIT 2 INTO OUTFILE '/tmp/test.csv' FIELDS TERMINATED BY '\t';
するとCSVファイルの内容は以下のようになります。2列目がunicode表現になっています。これから元の文字列を含んだjsonを復元したいんですが、unicode表現のまま復元されてしまいハマりました。
テストデータ ["\\u3042", "\\u3044", "\\u3046"]
結論を書くとこのデータをパースするには以下のようにします。ポイントはCSVファイルの形式にあわせて、csv.Dialectのサブクラスを作ってパース時に指定する事です。Dialect使わずに、CSVファイル側を微調整しようとしても巧く行きませんでした(CSVの仕様を完全に把握してたら出来るんだと思います。)。また、escapecharacterを指定しないとスラッシュがunescapeされずにjsonデータを復元できません。
#!/usr/bin/python # -*- coding: utf-8 -*- import csv import simplejson as json from prettyprint import pp class MySQLQuote(csv.Dialect): delimiter = '\t' quotechar = '\\' lineterminator = '\r\n' quoting = csv.QUOTE_ALL escapechar = '\\' def main(): reader = csv.reader(open('test.csv', 'rb'), MySQLQuote()) for line in reader: pp(json.loads(line[1])) if __name__ == '__main__': main()
僕はGAEを使っているので、データのアップロード時に使うCSVをこれで処理しています。

