書く csvモジュールでcsvファイルを。
今回はcsvモジュール
を使ってcsvファイルを書きます。
前回(csvの読み)
csvモジュールでcsvファイルを読む - よちよちpython
PandasでCSVファイルを読む - よちよちpython
(基本のみで詳細な説明なし)
作業環境
Androidスマホ
QpythonのQPyNotebook(python3.6)
目次
csvモジュールで書く
読むときと同様に、csvモジュール
を使います。import csv
。
標準モジュール
なのでインストール不要。
読みと同様、open()関数を使って、上書き保存のw
モードか、追記保存のa
モードでcsvファイルを開く。
その後csv.writer()
メソッドを使います。
1行ずつ書く
writerow()
を使います。
writerow
のrowは単数形!
1行ずつなので。
こんな感じで
with open(ファイル名,"w") as f: w = csv.writer(f) w.writerow(行ごとのデータ)
実際に書いてみます。
上書きモードで書き込みテスト
import csv # csvファイルの新規作成 file_name = "test_csv_writer.csv" # csvを上書きモードで開く with open(file_name,"w",newline="") as f: w1 = csv.writer(f) w1.writerow("書き込み1")
実行して書き込めたかどうか確かめます。
↓ スマホアプリのJota+で開く
お、も、て、な、し w
やはり1文字ずつセルに割り当てられている
↓ Excel 文字化けな上に列が少ない。
セルA1に与えた文字列を入れるにはどうしたらようございましょうか。
引数
はリストで入れる様に。
上書きモード書き込みテスト 2
引数をリストで与えます。
csvをExcelやGoogleスプレッドシート等で見る場合は、書き込み保存時の文字コードと開いた時の文字コードを一致させなければ文字化けしてしまう。
更に面倒なことにShift_jisで保存すると、Pythonで開くときにShift_jisと指示しなければエラーが出る。
encoding="shift_jis"
を付け加える。
import csv # csvファイルの新規作成 file_name = "test_csv_writer.csv" with open(file_name,"w",encoding="shift_jis") as f: w2 = csv.writer(f) w2.writerow(["書き込み2"])
↓ Excel文字化けなし。
上書き保存のw
モードで書いておりますので、上書きされました。
↓ Jota+ (読取文字コード自動判別) 文字化け。
encoding="shift_jis"だと、今度はExcel以外が文字化けしてしまった。
※
Googleスプレッドシートは、「Office互換モード」のExcel形式で保存されていると表示が出ている。
「Googleスプレッドシート形式に戻すボタン」を押せば文字化けは直ることは直る。
複数の値を1行に書く
要素が複数あるリストをwriterow
の引数に入れればよかとです(*´・ω・`)b。
import csv # csvファイルの新規作成 file_name = "test_csv_writer.csv" with open(file_name,"w",encoding="utf-8") as f: w3 = csv.writer(f) w3.writerow(["書き込み3-1","書き込み3-2","書き込み3-3"])
読んでみます。
with open(file_name,"r") as f: print(f.read())
書き込み3-1,書き込み3-2,書き込み3-3
複数の値を1行追加で書く
上の書き込みに1行追加してみます。
追記モード a
に変えます。
utf-8
で書き込みます。
import csv # csvファイルの新規作成 file_name = "test_csv_writer.csv" with open(file_name,"a",encoding="utf-8") as f: w4 = csv.writer(f) w4.writerow(["書き込み4-1","書き込み4-2","書き込み4-3","書き込み4-4","書き込み4-5"])
# 読み込み with open(file_name,"r") as f: print(f.read())
書き込み3-1,書き込み3-2,書き込み3-3
書き込み4-1,書き込み4-2,書き込み4-3,書き込み4-4,書き込み4-5
一度に複数行を書く
複数行をいっぺんに書き込みたければ、writerow
を複数形のwriterows
に変えればOK。
引数のリストも複数行ふやします。
上書き保存モードで3行書き込みます。
with open(file_name,"w",encoding="utf-8") as f: w5 = csv.writer(f) w5.writerows([ ["書き込み5-1-1","5-1-2","5-1-3"], ["5-2-1","5-2-2","5-2-3"], ["5-3-1","5-3-2","5-3-3"] ])
# 読み込み with open(file_name,"r") as f: print(f.read())
書き込み5-1-1,5-1-2,5-1-3
5-2-1,5-2-2,5-2-3
5-3-1,5-3-2,5-3-3
辞書型から書く
csv.DictWiter()
を使う。
各行のデータが以下のように辞書型で与えられたとする。
data1 = {"見出し1":"1-1","見出し2":"1-2","見出し3":"1-3"} data2 = {"見出し2":"2-2","見出し3":"2-3"}
1行ずつcsv.DictWriter()で書き込んでみよう
# 辞書型のデータ data1 = {"国語":57,"算数":65,"理科":59} data2 = {"社会":98,"英語":100} # 先頭行の項目 header1 = ["国語","算数","理科","社会","英語"] with open(file_name,"w") as f: w = csv.DictWriter(f,header1) w.writeheader() w.writerow(data1) w.writerow(data2)
書き込み実行しました。
読み込みます。
with open(file_name,"r") as f: print(f.read())
国語,算数,理科,社会,英語
57,65,59,,
,,,98,100
data2
の方は「見出し1」のデータが入っていませんが、上手く見出し通りに割り振られています。
複数の辞書型データを一度に書き込んでみよう
# 辞書型のデータ data1 = {"記録日":20190907,"商品番号":107,"入荷数":100} data2 = {"記録日":20190907,"商品番号":75,"売上数":25} # 先頭行の項目 header2 = ["記録日","商品番号","入荷数","売上数","在庫数"] with open (file_name,"w") as f: w2 = csv.DictWriter(f,header2) w2.writeheader() w2.writerows([data1,data2])
書き込みました。
↓ スプレッドシートで見ると
仕入や販売、在庫の管理に使えそうです。
項目にない辞書データを与えるとどうなる?
上記の2つのプログラムは、項目にちゃんと存在するデータを辞書型で与えています。
項目にないものを与えるとどうなるか実験。
# 辞書型のデータ data1 = {"記録日":20190907,"商品番号":107,"入荷数":100} data2 = {"記録日":20190907,"商品番号":75,"売上数":25} # 先頭行の項目 header3 = ["項目1","項目2","項目3","項目4","項目5"] with open (file_name,"w") as f: w3 = csv.DictWriter(f,header3) w3.writeheader() w3.writerows([data1,data2])
ValueErrorTraceback (most recent call last)
<ipython-input-59-3762afe82e13> in <module>()
10 w3 = csv.DictWriter(f,header3)
11 w3.writeheader()
---> 12 w3.writerows([data1,data2])
~/lib/python36.zip/csv.py in writerows(self, rowdicts)
156
157 def writerows(self, rowdicts):
--> 158 return self.writer.writerows(map(self._dict_to_list, rowdicts))
159
160 # Guard Sniffer's type checking against builds that exclude complex()
~/lib/python36.zip/csv.py in _dict_to_list(self, rowdict)
149 if wrong_fields:
150 raise ValueError("dict contains fields not in fieldnames: "
--> 151 + ", ".join([repr(x) for x in wrong_fields]))
152 return (rowdict.get(key, self.restval) for key in self.fieldnames)
153
ValueError: dict contains fields not in fieldnames: '商品番号', '入荷数', '記録日'
ValueError
と出ています。
dict contains fields not in fieldnames
フィールド名に存在しない辞書型を含んでいますよ、と。
今回はここまで。