よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

書く 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()を使います。

writerowrow単数形!
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+で開く

f:id:chayarokurokuro:20190907150255j:plain

お、も、て、な、し w


Googleスプレッドシートで開くと

f:id:chayarokurokuro:20190907150326j:plain

やはり1文字ずつセルに割り当てられている


Excel 文字化けな上に列が少ない。

f:id:chayarokurokuro:20190907150616j:plain



セルA1に与えた文字列を入れるにはどうしたらようございましょうか。

引数リストで入れる様に。


上書きモード書き込みテスト 2

引数をリストで与えます。

csvExcelGoogleスプレッドシート等で見る場合は、書き込み保存時の文字コードと開いた時の文字コードを一致させなければ文字化けしてしまう。
更に面倒なことに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文字化けなし。

f:id:chayarokurokuro:20190907150740j:plain

上書き保存のwモードで書いておりますので、上書きされました。


↓ Jota+ (読取文字コード自動判別) 文字化け。

f:id:chayarokurokuro:20190907150805j:plain


Googleスプレッドシート 文字化け

f:id:chayarokurokuro:20190907150825j:plain

encoding="shift_jis"だと、今度はExcel以外が文字化けしてしまった。



Googleスプレッドシートは、「Office互換モード」のExcel形式で保存されていると表示が出ている。

f:id:chayarokurokuro:20190907151251j:plain


Googleスプレッドシート形式に戻すボタン」を押せば文字化けは直ることは直る。

f:id:chayarokurokuro:20190907151320j:plain


複数の値を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])

書き込みました。

スプレッドシートで見ると

f:id:chayarokurokuro:20190907152233j:plain


仕入や販売、在庫の管理に使えそうです。


項目にない辞書データを与えるとどうなる?


上記の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 フィールド名に存在しない辞書型を含んでいますよ、と。


今回はここまで。