Python | 1 日 120 分 × 7 日アプリ学習:CSVファイル読み書きアプリ(中級編)

Web APP Python
スポンサーリンク

1日目のゴール

1日目のテーマは
「csvモジュールを使って、CSVファイルを“怖くない実務データ”として扱える感覚をつかむこと」 です。

今日つかみたいのは、この2つです。

CSVってそもそも何者か(ただのテキストファイルだという感覚)
csv モジュールで「読む」「書く」の最小パターン

ここが見えれば、明日以降の「集計」「フィルタ」「変換」が一気に楽になります。


CSVファイルって何?をちゃんとイメージする

Excelファイルとの違いをざっくり理解する

まず、「CSVって何?」を言葉でつかみます。

CSV は
Comma Separated Values
=「カンマで区切られた値たち」

という意味の、ただのテキストファイルです。

例えば、こんな内容のファイルがあったとします。

id,name,age
1,Taro,25
2,Hanako,30
3,Ken,22

1行目は「列の名前」
2行目以降は「1人分のデータ」
カンマで区切られているだけのテキストです。

Excel で開くと表っぽく見えますが、
中身はあくまで「文字列の行が並んでいるだけ」です。

ここをちゃんと理解しておくと、
「Python で扱うのが怖くなくなる」んですよね。


csvモジュールを使う理由

自分で split してもいいけど…?

実は、CSVはテキストなので、
極論を言えばこうやっても読めます。

line = "1,Taro,25"
parts = line.split(",")
# ["1", "Taro", "25"]
Python

でも、現実のCSVはもっとややこしいです。

名前にカンマが入っている
「”」で囲まれている
改行を含むセルがある

こういうケースを自前で全部処理するのは、かなりしんどいです。

そこで登場するのが csv モジュールです。

csv は、
「CSVの面倒なルールを全部知っていて、いい感じに読み書きしてくれるやつ」
だと思ってください。


まずは読み込みの最小パターンを覚える

csv.reader で「行ごとのリスト」として読む

一番シンプルな読み方からいきます。

事前に、こんな people.csv があるとします。

id,name,age
1,Taro,25
2,Hanako,30
3,Ken,22

これを Python で読み込んで、
1行ずつ表示してみましょう。

import csv

def read_csv_basic():
    with open("people.csv", "r", encoding="utf-8", newline="") as f:
        reader = csv.reader(f)

        for row in reader:
            print(row)

read_csv_basic()
Python

実行すると、こんな感じで出ます。

['id', 'name', 'age']
['1', 'Taro', '25']
['2', 'Hanako', '30']
['3', 'Ken', '22']

ここで深掘りしたいポイントがいくつかあります。

csv.reader(f) は、「ファイル f をCSVとして読むためのオブジェクト」を返す。
for row in reader: で「1行ずつ、リストとして取り出している」。
row は「文字列のリスト」であり、数字も一旦は文字列として入っている。

つまり、

「CSVの1行=Pythonでは“文字列のリスト”として扱う」

という感覚を持てればOKです。


ヘッダー行をスキップして読む

1行目は「列名」として扱いたい

実務では、1行目は「ヘッダー(列名)」であることが多いです。

さっきの people.csv もそうでした。

id,name,age   ← ヘッダー
1,Taro,25
2,Hanako,30
3,Ken,22

「データとして扱うのは2行目以降だけにしたい」
という場合、こう書けます。

import csv

def read_csv_skip_header():
    with open("people.csv", "r", encoding="utf-8", newline="") as f:
        reader = csv.reader(f)

        header = next(reader)  # 1行目を読み飛ばす
        print("ヘッダー:", header)

        for row in reader:
            print("データ行:", row)

read_csv_skip_header()
Python

ここでの重要ポイントは、

next(reader) で「最初の1行だけ先に読む」こと。
その後の for row in reader: では、2行目以降が順番に出てくること。

この「ヘッダーを next で1回読む」というパターンは、
CSVを扱うときの定番テクニックです。


行のリストを「意味のある変数」に割り当てる

インデックスのままだと読みにくい

さっきの row は、こんなリストでした。

row = ['1', 'Taro', '25']
Python

これをそのまま row[0], row[1], row[2] と使うと、
「どれが何の列か」が分かりにくくなります。

そこで、こうします。

import csv

def read_csv_with_unpack():
    with open("people.csv", "r", encoding="utf-8", newline="") as f:
        reader = csv.reader(f)
        next(reader)  # ヘッダーを読み飛ばす

        for row in reader:
            person_id, name, age_text = row
            age = int(age_text)

            print(f"ID={person_id}, 名前={name}, 年齢={age}")
Python

ここで深掘りしたいのは、

person_id, name, age_text = row という「アンパック」の書き方。
row[0] などを使わず、「意味のある名前の変数」に分解していること。
年齢は int() で整数に変換してから使っていること。

これで、コードの読みやすさが一気に上がります。


csv.writer でCSVファイルに書き込む

まずは「新規に書き出す」パターン

今度は逆方向、「書く」側です。

例えば、Python の中にこんなデータがあるとします。

people = [
    ["id", "name", "age"],
    ["1", "Taro", "25"],
    ["2", "Hanako", "30"],
    ["3", "Ken", "22"],
]
Python

これを output.csv に書き出してみます。

import csv

def write_csv_basic():
    people = [
        ["id", "name", "age"],
        ["1", "Taro", "25"],
        ["2", "Hanako", "30"],
        ["3", "Ken", "22"],
    ]

    with open("output.csv", "w", encoding="utf-8", newline="") as f:
        writer = csv.writer(f)

        for row in people:
            writer.writerow(row)

    print("output.csv に書き込みました。")
Python

ここでの重要ポイントは、

csv.writer(f) で「CSVとして書くためのオブジェクト」を作っていること。
writer.writerow(row) に「リスト」を渡すと、そのまま1行分として書かれること。
newline="" を open に渡しているのは、「余計な空行が入る問題」を防ぐための定番設定であること。

これで、output.csv の中身はこうなります。

id,name,age
1,Taro,25
2,Hanako,30
3,Ken,22

実務っぽいミニアプリ:CSVを読み込んで、別のCSVに変換する

「読み込み」と「書き込み」をつなげてみる

1日目の仕上げとして、
こんなミニアプリを考えてみましょう。

people.csv を読み込む
年齢が 25 歳以上の人だけを抽出する
その結果を people_over25.csv に書き出す

コードはこうなります。

import csv

def filter_people_over_25(input_file, output_file):
    with open(input_file, "r", encoding="utf-8", newline="") as f_in:
        reader = csv.reader(f_in)
        header = next(reader)

        filtered_rows = []
        filtered_rows.append(header)

        for row in reader:
            person_id, name, age_text = row
            age = int(age_text)

            if age >= 25:
                filtered_rows.append(row)

    with open(output_file, "w", encoding="utf-8", newline="") as f_out:
        writer = csv.writer(f_out)
        for row in filtered_rows:
            writer.writerow(row)

    print(f"{output_file} に 25歳以上のデータを書き出しました。")


def main():
    filter_people_over_25("people.csv", "people_over25.csv")


main()
Python

このコードを、日本語だけで分解してみます。

入力ファイルを開き、csv.reader で読む準備をする。
ヘッダーを1行読み飛ばしつつ、filtered_rows にまずヘッダーを入れておく。
2行目以降を1行ずつ読み、年齢を整数に変換する。
25歳以上なら、その行を filtered_rows に追加する。
読み終わったら、出力ファイルを開き、csv.writer で filtered_rows を1行ずつ書き出す。

これだけで、

「CSVを読み込んで条件でフィルタし、別のCSVとして出力する」

という、かなり実務寄りの処理ができています。


1日目で絶対に押さえておきたいポイント

「CSV+csvモジュール」の頭の中の地図

今日の本質を、ぎゅっとまとめるとこうです。

CSV は「カンマ区切りのテキスト」であり、1行=1レコード。
csv.reader は「1行を“文字列のリスト”として返してくれる読み取り器」。
csv.writer は「“文字列のリスト”を1行として書き出してくれる書き込み器」。
ヘッダー行は next(reader) で1回だけ先に読むのが定番。
行のリストは「意味のある変数」にアンパックしてから使うと読みやすい。

2日目以降は、
ここに「辞書形式で読む」「列名でアクセスする」「集計する」などを足していきます。

でも、土台は今日やったこの2つだけです。

「読む(reader)」
「書く(writer)」

この感覚さえつかめていれば、
CSVはもう“実務データ”として怖くありません。

タイトルとURLをコピーしました