pythonのcsvモジュールで詰まった話

#この記事について

python勉強中です。

csvモジュール縛りで色々やろうとしたところ、詰まってしまったので備忘録。
「pandas使えよ」って5回くらい思われるだろうなって感じですが、csvモジュール縛りに意味があるんだ！ということでやっておりました。はい。
いやその縛り意味あんのかよって言われると、そこは、もう、はい、すみません。

#やりたかったこと

csvモジュールしか使わない、という前提のもと、
既存のcsvファイルにカウントアップで上書きする。

csvファイルにはNAMEとCOUNTという列があり、
NAMEにはレストランの名前が、COUNTには数字が入る。

●CSVの例
NAME,COUNT
sukiya,1
matsuya,1
yoshinoya,2


#最初に書いたコード
```python:csv_train.py

import csv

fieldnames =  ["NAME", "COUNT"]

# CSVファイルを読み取りで開く。また、行数を数えておく。
with open("csv_train.csv", "r", newline="") as csv_file:
    reader = csv.DictReader(csv_file)
    reader_list = list(reader)
    rows_cnt = len(reader_list)

# CSVにデータがあれば、レコメンドを出す
if rows_cnt >= 1:
    # 今何行目を読んでいるのかのカウント変数
    t = 1
    for row in reader_list:
        print("My recommended retaurant is " + row["NAME"] + ".")
        print("Do you like this restaurant? [Yes/No]")
        ans = input()

        # レコメンドに対してユーザーが「好き」と答えたら
        if ans == "Yes":
            with open("csv_train.csv", "w", newline="") as csv_file:
                writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
                writer.writeheader()
                i = 1
                for row in reader_list:
                    if i == t:
                        cnt = int(row["COUNT"]) + 1
                        writer.writerow({"NAME": row["NAME"], "COUNT": cnt})
                    else:
                        writer.writerow({"NAME": row["NAME"], "COUNT": row["COUNT"]})
                    i += 1

        # レコメンドに対してユーザーが「好きではない」と答えたら
        else:
            pass

        # カウント変数をカウントアップ
        t += 1

# お礼を言ってクローズ
print("Have a good day!")

```
#何がしたいコードなのか
CSVモジュールを使ったデータの上書きについて、一行目から順番に更新していく、というやり方しか見当たらなかった（たぶん調べ方が悪いのだろう）。
なので、更新したい行数を指定してあげて、その行は更新するが、それ以外の行は元のデータの内容で上書き、という処理にした。

だいぶ頭の悪い処理だけど、他に思いつかなかった…

#何が起きるか？
データの最終行しかカウントアップされない。

#なぜか？
一番最初にcsvを読み込むときに、reader_listにcsvの中身を格納している。
また、書き込む際もreader_listに対してforを回して処理しようとしている。
だけど、このreader_listは最初に読み込んだ際のreader_listなので、
書き込み処理をする都度、一番最初のCSVの内容に戻ってしまう。

結果、一番最後の書き込み処理しか反映されないことになる。

#どうしたらいいのか？
書き込み処理をする都度、reader_listを更新してあげればよい。

```python:csv_train.py

import csv

fieldnames =  ["NAME", "COUNT"]

# CSVファイルを読み取りで開く。また、行数を数えておく。
with open("csv_train.csv", "r", newline="") as csv_file:
    reader = csv.DictReader(csv_file)
    reader_list = list(reader)
    rows_cnt = len(reader_list)

# CSVにデータがあれば、レコメンドを出す
if rows_cnt >= 1:
    # 今何行目を読んでいるのかのカウント変数
    t = 1
    for row in reader_list:
        print("My recommended retaurant is " + row["NAME"] + ".")
        print("Do you like this restaurant? [Yes/No]")
        ans = input()

        # レコメンドに対してユーザーが「好き」と答えたら
        if ans == "Yes":
            
            #この処理を追加。書き込み前にreader_listを新しいのに変える。
            with open("csv_train.csv", "r", newline="") as csv_file:
                reader = csv.DictReader(csv_file)
                reader_list = list(reader)

            with open("csv_train.csv", "w", newline="") as csv_file:
                writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
                writer.writeheader()
                i = 1
                for row in reader_list:
                    if i == t:
                        cnt = int(row["COUNT"]) + 1
                        writer.writerow({"NAME": row["NAME"], "COUNT": cnt})
                    else:
                        writer.writerow({"NAME": row["NAME"], "COUNT": row["COUNT"]})
                    i += 1

        # レコメンドに対してユーザーが「好きではない」と答えたら
        else:
            pass

        # カウント変数をカウントアップ
        t += 1

# お礼を言ってクローズ
print("Have a good day!")

```

#感想
CSVモジュールを使ったデータの更新処理が、ほんとにこういうやり方しかないのか？と思いながら書いてた。なんか無理やり解決した感がすごい。
「こういうの熟練の皆様はどういう風に書くのだろう」という興味で、コメントが貰えれば万々歳、スルーされてもやむなし、くらいの気持ちで、Qiita初投稿してみました。

初めて書いた記事がほんとにこれでいいのだろうか自分。あとで消したくなったりしないだろうか自分。どうだろうか自分。

なにはともあれ、最後まで読んでくださった方、有難うございました。