プログラミング

PythonでCSVを1行ずつ読み込むには?csv.readerも解説!(CSV処理:逐次読み込み:データ処理:ファイル読み込み:パースなど)

当サイトでは記事内に広告を含みます

PythonでCSVファイルを扱う場面は、データ分析・売上管理・ログ処理など業務システムから趣味のプログラミングまで非常に幅広くあります。大量のデータが入ったCSVファイルを効率よく処理するには、1行ずつ読み込んで逐次処理する方法が基本となります。

Pythonには標準ライブラリのcsvモジュールが用意されており、csv.readerを使うことでCSVファイルを1行ずつ簡単にパース・処理できます。また、辞書形式で読み込めるcsv.DictReaderも合わせて知っておくと、ヘッダー付きCSVの処理がより直感的に書けるようになります。

この記事では、PythonでCSVを1行ずつ読み込む方法を、csv.readerの基本・DictReader・エンコード対応・応用パターンまで、サンプルコードとともにわかりやすく解説していきます。

PythonでCSVを1行ずつ読み込むにはcsv.readerが基本

それではまず、PythonでCSVファイルを1行ずつ読み込む基本的な方法について解説していきます。

Pythonの標準ライブラリのcsvモジュールを使うと、csv.readerにファイルオブジェクトを渡すだけでCSVを1行ずつリストとして読み込めるようになります。カンマ区切りの解析も自動で行ってくれます。


import csv

# サンプルCSVファイルを作成
with open("/home/claude/products.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["商品名", "価格", "在庫数"])
    writer.writerow(["アボカド", 298, 50])
    writer.writerow(["ドラゴンフルーツ", 498, 30])
    writer.writerow(["サーモン", 1200, 20])
    writer.writerow(["ゴリラ茶", 350, 100])

# csv.readerで1行ずつ読み込む
with open("/home/claude/products.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# 出力結果:['商品名', '価格', '在庫数']
# 出力結果:['アボカド', '298', '50']
# 出力結果:['ドラゴンフルーツ', '498', '30']
# 出力結果:['サーモン', '1200', '20']
# 出力結果:['ゴリラ茶', '350', '100']

csv.readerはCSVの各行をリストとして返します。数値もすべて文字列として読み込まれるため、計算に使う場合はint()やfloat()で型変換が必要です。

CSVファイルを書き込む際はnewline=””を指定しないと、Windowsで空行が挿入される場合があります。読み込みは通常のopen()で問題ありませんが、書き込みには必ずnewline=””をつける習慣をつけましょう。

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


import csv

# ヘッダー行をスキップしてデータ行だけ処理する
with open("/home/claude/products.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)

    # next()でヘッダー行を読み飛ばす
    header = next(reader)
    print(f"ヘッダー:{header}")

    # 残りのデータ行を処理
    for row in reader:
        name = row[0]
        price = int(row)
        stock = int(row)
        print(f"{name}:{price}円 / 在庫{stock}個")

# 出力結果:ヘッダー:['商品名', '価格', '在庫数']
# 出力結果:アボカド:298円 / 在庫50個
# 出力結果:ドラゴンフルーツ:498円 / 在庫30個
# 出力結果:サーモン:1200円 / 在庫20個
# 出力結果:ゴリラ茶:350円 / 在庫100個

next()を1回呼び出すことで、ヘッダー行だけを取り出してイテレータを次の行に進められます。ヘッダーの内容も変数に保存しておくと後で参照できます。

行番号と一緒に読み込む


import csv

# enumerate()で行番号と一緒に読み込む
with open("/home/claude/products.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for i, row in enumerate(reader):
        if i == 0:
            print(f"ヘッダー行:{row}")
        else:
            print(f"{i}行目:{row[0]} / {row}円")

# 出力結果:ヘッダー行:['商品名', '価格', '在庫数']
# 出力結果:1行目:アボカド / 298円
# 出力結果:2行目:ドラゴンフルーツ / 498円
# 出力結果:3行目:サーモン / 1200円
# 出力結果:4行目:ゴリラ茶 / 350円

enumerate()を使うと行番号でヘッダーとデータを分岐させる処理が簡単に書けます。エラー発生時の行番号特定にも役立ちます。

csv.DictReaderで辞書形式に読み込む方法

続いては、csv.DictReaderを使ってCSVを辞書形式で読み込む方法を確認していきます。

csv.DictReaderを使うと、ヘッダー行の列名をキーとして各行を辞書形式で取得できます。インデックスではなく列名でアクセスできるため、コードの可読性が大幅に向上します。

DictReaderの基本的な使い方


import csv

# DictReaderで辞書形式に読み込む
with open("/home/claude/products.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(dict(row))

# 出力結果:{'商品名': 'アボカド', '価格': '298', '在庫数': '50'}
# 出力結果:{'商品名': 'ドラゴンフルーツ', '価格': '498', '在庫数': '30'}
# 出力結果:{'商品名': 'サーモン', '価格': '1200', '在庫数': '20'}
# 出力結果:{'商品名': 'ゴリラ茶', '価格': '350', '在庫数': '100'}

DictReaderは1行目をヘッダーとして自動的に認識し、以降のデータ行を辞書として返します。列名が変わってもインデックス番号の修正が不要なため、保守性の高いコードが書けます。

DictReaderで列名を使ってデータを処理する


import csv

# 列名でアクセスして計算処理を行う
total = 0

with open("/home/claude/products.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        name = row["商品名"]
        price = int(row["価格"])
        stock = int(row["在庫数"])
        subtotal = price * stock
        total += subtotal
        print(f"{name}:{price}円 × {stock}個 = {subtotal:,}円")

print(f"合計在庫金額:{total:,}円")

# 出力結果:アボカド:298円 × 50個 = 14,900円
# 出力結果:ドラゴンフルーツ:498円 × 30個 = 14,940円
# 出力結果:サーモン:1200円 × 20個 = 24,000円
# 出力結果:ゴリラ茶:350円 × 100個 = 35,000円
# 出力結果:合計在庫金額:88,840円

row[“商品名”]のように列名でアクセスするコードは、row[0]よりもはるかに読みやすく意図が伝わりやすくなります。列の順番が変わっても動作に影響しない点も大きなメリットです。

readerとDictReaderの使い分け

方法 アクセス方法 ヘッダー処理 向いている場面
csv.reader インデックス(row[0]) 手動でスキップ シンプルな処理・ヘッダーなしCSV
csv.DictReader 列名(row[“名前”]) 自動認識 ヘッダーあり・可読性重視

エンコードと区切り文字を指定した読み込み方法

続いては、文字コードや区切り文字をカスタマイズしてCSVを読み込む方法を確認していきます。

実際の業務で使われるCSVファイルはShift-JISのエンコードやタブ区切り・セミコロン区切りなど、標準とは異なる形式であることも多いものです。対応方法を把握しておくことが重要です。

Shift-JISのCSVを読み込む方法


import csv

# Shift-JISのCSVファイルを作成(Windowsのエクセル出力を想定)
with open("/home/claude/sjis_products.csv", "w", encoding="shift-jis", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["商品名", "価格"])
    writer.writerow(["キーボード", 8500])
    writer.writerow(["マウス", 2000])

# Shift-JISで読み込む
with open("/home/claude/sjis_products.csv", "r", encoding="shift-jis") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['商品名']}:{row['価格']}円")

# 出力結果:キーボード:8500円
# 出力結果:マウス:2000円

open()のencodingパラメータをshift-jisに変更するだけでShift-JISのCSVに対応できます。WindowsのExcelで保存したCSVは多くの場合Shift-JISになっているため、この対応は実務で非常によく使われます。

タブ区切り・セミコロン区切りに対応する


import csv

# タブ区切りファイル(TSV)を作成
with open("/home/claude/products.tsv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f, delimiter="\t")
    writer.writerow(["商品名", "価格", "在庫"])
    writer.writerow(["ネジ", 50, 500])
    writer.writerow(["ボルト", 120, 300])

# タブ区切りで読み込む
with open("/home/claude/products.tsv", "r", encoding="utf-8") as f:
    reader = csv.reader(f, delimiter="\t")
    for row in reader:
        print(row)

# 出力結果:['商品名', '価格', '在庫']
# 出力結果:['ネジ', '50', '500']
# 出力結果:['ボルト', '120', '300']

csv.reader()のdelimiterパラメータで区切り文字を指定します。タブ区切りなら”\t”、セミコロン区切りなら”;”を指定するだけで対応できます。

クォートや特殊文字を含むCSVを読み込む


import csv

# クォートやカンマを含むデータのCSVを作成
with open("/home/claude/special.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["商品名", "説明", "価格"])
    writer.writerow(["アボカド", "濃厚でクリーミー、栄養満点", 298])
    writer.writerow(["サーモン", "「新鮮」な刺身用サーモン", 1200])

# csv.readerは自動的にクォートを処理してくれる
with open("/home/claude/special.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# 出力結果:['商品名', '説明', '価格']
# 出力結果:['アボカド', '濃厚でクリーミー、栄養満点', '298']
# 出力結果:['サーモン', '「新鮮」な刺身用サーモン', '1200']

csv.readerはフィールド内にカンマや改行が含まれる場合もクォートを解釈して正しく分割してくれます。手動でsplit(“,”)を使うよりもcsvモジュールを使う方が安全で確実です。

CSVを1行ずつ読み込む応用パターン

続いては、CSVを1行ずつ読み込みながら実践的な処理を行う応用パターンを確認していきます。

CSVの逐次読み込みはデータのフィルタリング・集計・変換・別ファイルへの書き出しなど、様々な処理と組み合わせて活用できます。

条件に合う行だけを抽出して別ファイルに書き出す


import csv

# 価格が500円以上の商品だけを別ファイルに書き出す
with open("/home/claude/products.csv", "r", encoding="utf-8") as infile, \
     open("/home/claude/expensive.csv", "w", encoding="utf-8", newline="") as outfile:

    reader = csv.DictReader(infile)
    writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames)
    writer.writeheader()

    for row in reader:
        if int(row["価格"]) >= 500:
            writer.writerow(row)

# 結果を確認
with open("/home/claude/expensive.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['商品名']}:{row['価格']}円")

# 出力結果:サーモン:1200円

入力ファイルと出力ファイルを同時にwith文で開いて、条件に合う行だけを書き出すパターンです。大容量CSVのフィルタリングにメモリを圧迫せずに対応できます。

CSVを読み込んでデータを集計する


import csv
from collections import defaultdict

# カテゴリ別の集計CSVを作成
with open("/home/claude/sales.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["商品名", "カテゴリ", "売上"])
    writer.writerow(["アボカド", "食品", 29800])
    writer.writerow(["キーボード", "PC周辺機器", 85000])
    writer.writerow(["サーモン", "食品", 60000])
    writer.writerow(["マウス", "PC周辺機器", 40000])
    writer.writerow(["ドラゴンフルーツ", "食品", 14940])

# カテゴリ別に集計
category_total = defaultdict(int)

with open("/home/claude/sales.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        category_total[row["カテゴリ"]] += int(row["売上"])

for category, total in category_total.items():
    print(f"{category}:{total:,}円")

# 出力結果:食品:104,740円
# 出力結果:PC周辺機器:125,000円

defaultdict(int)とDictReaderを組み合わせることで、CSVのカテゴリ別集計が簡潔に書けます。pandasを使わなくても標準ライブラリだけでシンプルな集計処理が実現できます。

大容量CSVをチャンク単位で処理する


import csv

def read_csv_chunks(filepath, chunk_size=3):
    """CSVをchunk_size行ずつまとめて処理するジェネレータ"""
    with open(filepath, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        chunk = []
        for row in reader:
            chunk.append(row)
            if len(chunk) >= chunk_size:
                yield chunk
                chunk = []
        if chunk:
            yield chunk

# チャンク単位で処理
for chunk_num, chunk in enumerate(read_csv_chunks("/home/claude/products.csv"), 1):
    print(f"チャンク{chunk_num}({len(chunk)}行):")
    for row in chunk:
        print(f"  {row['商品名']}:{row['価格']}円")

# 出力結果:チャンク1(3行):
# 出力結果:  アボカド:298円
# 出力結果:  ドラゴンフルーツ:498円
# 出力結果:  サーモン:1200円
# 出力結果:チャンク2(1行):
# 出力結果:  ゴリラ茶:350円

ジェネレータを使ったチャンク処理は、大容量CSVをまとめてデータベースに挿入したり、バッチ処理を行う場合に非常に効果的なパターンです。

まとめ

この記事では、PythonでCSVを1行ずつ読み込む方法について、csv.readerの基本・DictReaderによる辞書形式の読み込み・エンコードと区切り文字の指定・応用パターンまで幅広く解説しました。

CSVの基本的な読み込みにはcsv.readerを使い、forループで1行ずつ処理するのが定番です。ヘッダー付きCSVにはcsv.DictReaderを使うと列名でアクセスできてコードの可読性が上がります。WindowsのExcel出力などShift-JISのCSVにはencoding=”shift-jis”の指定が必要です。

フィルタリング・集計・別ファイルへの書き出しなど、今回紹介したパターンを組み合わせることで実務のCSV処理のほとんどに対応できます。ぜひ実際のプロジェクトで活用してみてください。

CSVの読み込みにはsplit(“,”)ではなく必ずcsvモジュールを使いましょう。フィールド内のカンマ・改行・クォートを含むデータを正しく処理できるのはcsvモジュールの大きな強みです。また文字化け防止のためencoding指定を忘れずに行うことがCSV処理のポイントです。