Python | ファイル・OS 操作:CSV DictReader

Python Python
スポンサーリンク

概要(DictReaderは「列名でアクセスできる」CSV読み込みの定番)

csv.DictReaderは、CSVの各行を「ヘッダーをキーにした辞書」として読み込める標準機能です。列名で参照できるので、インデックス番号を覚える必要がなく、可読性が抜群になります。重要なのは「エンコーディングと改行の扱い」「型変換・欠損値の安全処理」「ヘッダーがないCSVへの対応」です。with文でファイルを開き、必要に応じてfieldnamesやdialect(delimiterなど)を指定すれば、多くの現場のCSVを安全に扱えます。


基本の使い方(ここが重要)

ヘッダー行ありのCSVを辞書で読む

import csv

# 例: sample.csv の内容
# name,age,city
# Alice,30,New York
# Bob,25,Los Angeles

with open("sample.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row)  # {'name': 'Alice', 'age': '30', 'city': 'New York'} など
        print(row["name"], int(row["age"]))
Python

「newline=”」は改行の二重解釈を避けるための推奨設定です。値は文字列として読み込まれるため、数値が必要なら明示的に型変換します。

Pathlibと組み合わせて安全に扱う

from pathlib import Path
import csv

csv_path = Path("data/users.csv")
with csv_path.open(newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        ...
Python

Path.openを使うと結合や存在確認と一体で扱えます。


重要ポイントの深掘り(ヘッダー・型変換・欠損・方言)

ヘッダーがないCSVはfieldnamesを手動指定

import csv

# 例: ヘッダーなし
# Alice,30,New York
# Bob,25,Los Angeles

with open("noheader.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f, fieldnames=["name", "age", "city"])
    for row in reader:
        print(row)
Python

先頭行がデータの場合は、意図した列名を与えて辞書化します。先頭行をスキップしたいなら、事前に次(f)で1行読み捨てする方法もあります。

型変換とバリデーション(安全な変換関数の導入)

def to_int(s, default=None):
    try:
        return int(s)
    except (TypeError, ValueError):
        return default

with open("sample.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        age = to_int(row.get("age"))
        if age is None:
            # 欠損や不正値の扱いを統一(スキップ・ログ出力など)
            continue
        ...
Python

DictReaderは値を文字列で渡すので、変換と検証は必須です。小さなユーティリティ関数に切り出すと、コード全体が安定します。

欠損列・余分列の扱い(restval・restkey・extrasaction)

import csv

with open("messy.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(
        f,
        fieldnames=["name", "age", "city"],
        restval="",             # 足りない列のデフォルト値
        restkey="__extra__",    # 余分列のキー名(可変長行の吸収先)
    )
    for row in reader:
        print(row.get("__extra__"))  # 余分列があればここに入る
Python

列不足をrestvalで埋め、列過多はrestkeyで受け止めると、崩れたCSVでも耐性が上がります。余分列を拒否したい場合は、読み取り後にチェックして例外を出す設計にします。

区切り文字や引用符など「方言」の指定

import csv

with open("data_semicolon.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f, delimiter=";", quotechar='"')
    for row in reader:
        ...
Python

Excel由来などで「;」区切りになることがあります。delimiter・quotechar・escapecharを正しく指定すると、取りこぼしを防げます。


実務での使いどころ(クリーニング・集計・BOM・大規模)

クリーニングとフィルタ・集計の定番パターン

import csv

total = 0
count = 0
with open("sales.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        price = row.get("price", "").strip()
        if not price:
            continue
        total += float(price)
        count += 1
print("avg:", total / count if count else 0)
Python

stripで空白を落とし、欠損をスキップしてから集計。最初に「必須列があるか」を検証するのも有効です。

UTF-8 BOM対策と改行の取り扱い

import csv

# BOM付きの可能性がある場合は utf-8-sig にすると先頭の不可視文字を除去
with open("maybe_bom.csv", newline="", encoding="utf-8-sig") as f:
    reader = csv.DictReader(f)
    ...
Python

BOMがあるとヘッダーの先頭に不可視文字が付く事故が起きます。utf-8-sigで回避できます。

大規模CSVは「イテレートして処理、作らず流す」

import csv

with open("huge.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for i, row in enumerate(reader, start=1):
        # その場で処理(DB投入・書き出しなど)
        ...
        if i % 100000 == 0:
            print("processed:", i)
Python

一度にメモリへ読み込まず、行ごとに処理します。ログを入れると進捗が見えて安心です。


例題で身につける(定番から一歩先まで)

例題1:基本読み込みと型変換

import csv

with open("users.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        uid = row["id"]
        age = int(row["age"])  # 失敗可能なら try/except へ
        print(uid, age)
Python

例題2:ヘッダーなしCSVへの列名付与

import csv

with open("noheader.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f, fieldnames=["name", "age", "city"])
    for row in reader:
        print(row["name"], row["city"])
Python

例題3:セミコロン区切り+引用符ありの読取り

import csv

with open("data_semicolon.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f, delimiter=";", quotechar='"')
    for row in reader:
        print(row)
Python

例題4:欠損をrestvalで埋め、余分列をrestkeyへ逃がす

import csv

with open("ragged.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(
        f,
        fieldnames=["id", "name", "score"],
        restval=None,
        restkey="__extra__",
    )
    for row in reader:
        print(row["id"], row["name"], row["score"], row.get("__extra__"))
Python

例題5:DictWriterと組み合わせて「読み→加工→書き」

import csv

with open("input.csv", newline="", encoding="utf-8") as fin, \
     open("output.csv", "w", newline="", encoding="utf-8") as fout:
    reader = csv.DictReader(fin)
    fieldnames = reader.fieldnames + ["score2"]
    writer = csv.DictWriter(fout, fieldnames=fieldnames)
    writer.writeheader()
    for row in reader:
        row["score2"] = float(row["score"]) * 2 if row.get("score") else ""
        writer.writerow(row)
Python

DictReaderで辞書を受け、辞書のままDictWriterへ渡せば、列操作が明快になります。


まとめ

csv.DictReaderは「列名でアクセスできる」ことが最大の強みで、初心者でも安全に実務のCSVを扱えます。改行はnewline=”、エンコーディングはutf-8(BOMの可能性があればutf-8-sig)を基本に、値は文字列で来る前提で型変換・バリデーションを入れる。ヘッダーがない場合はfieldnamesを自前で定義し、崩れたCSVにはrestval・restkeyで耐性を持たせる。区切りや引用符はdialect指定で吸収し、巨大ファイルは行ごとに“作らず流す”。Pathlibとの併用で結合・存在確認・読み書きまで一貫させれば、短くて読みやすく、壊れないCSV処理が書けます。

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