Python:ファイル入出力(with構文 / CSV)
1学習の目的
- with構文でファイルを安全に読み書きできるようになる。閉じ忘れや文字化けといった定番の事故を避けられるようになる。
- csvモジュールで表形式データを取り込み、加工して別ファイルに保存できるようになる。ここまで来るとExcel作業の自動化が現実的な射程に入る。
2基礎解説
| やりたいこと | 書き方 | 注意点 |
|---|---|---|
| 書き込む | open("f.txt", "w") | 既存の内容は消える |
| 追記する | open("f.txt", "a") | 末尾に足す |
| 読み込む | open("f.txt") | モード省略時は読み込み |
| CSVを扱う | csv.reader / csv.writer | split より安全 |
- 必ず with open(...) as f: を使う。ブロックを抜けると自動で閉じるので close() の書き忘れが起きない。
- モード "w" は既存の内容を消してから書く。追記したいときは "a"。うっかり "w" でデータを消すのは定番の事故。
- 日本語を含むなら encoding="utf-8" を必ず指定する。省略すると環境によって文字化けやエラーになる。
- 1行ずつ読むのは for line in f:。行末に改行が付いているので line.strip() で取り除く。
- CSVは自作の split(",") ではなく csv モジュールを使う。値の中にカンマや改行が含まれていても正しく処理できる。
現場使用例:処理ログの記録、集計結果のレポート保存、取引先から届いたCSVの取り込み、設定ファイルの読み込み、抽出結果を別CSVに書き出して共有。
# 書き込む(既存の内容は消える)
with open("memo.txt", "w", encoding="utf-8") as f:
f.write("1行目\n")
f.write("2行目\n")
# 追記する
with open("memo.txt", "a", encoding="utf-8") as f:
f.write("3行目\n")
# 1行ずつ読む
with open("memo.txt", encoding="utf-8") as f:
for line in f:
print(line.strip())
# CSVを書いて読む
import csv
with open("data.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(["名前", "点数"])
writer.writerow(["田中", 82])
with open("data.csv", encoding="utf-8") as f:
for row in csv.reader(f):
print(row) # ['名前', '点数'] → ['田中', '82']
3基本ドリル(10問)
出力 == こんにちは
書き込みは with open("hello.txt", "w", encoding="utf-8") as f: の中で f.write(...)。読み込みは f.read()。
with open("hello.txt", "w", encoding="utf-8") as f:
f.write("こんにちは")
with open("hello.txt", encoding="utf-8") as f:
print(f.read())
書く→読むの最小形。with を2回書いているが、書き込みが完全に終わってから読むためにこれが正しい。
A. 末尾に追記される B. 既存の内容が消える C. エラーになる D. 読み込み専用になる 選択★☆☆無料
解答 == B
"w" は write の w。追記は別のモード。
B
開いた瞬間に中身が空になる。大事なファイルを "w" で開いて全消しは実務でも起こる事故。追記は "a"。
出力 == AB
2回目は "a" モードで開く。"w" だと A が消えてしまう。
with open("log.txt", "w", encoding="utf-8") as f:
f.write("A")
with open("log.txt", "a", encoding="utf-8") as f:
f.write("B")
with open("log.txt", encoding="utf-8") as f:
print(f.read())
"a" は append の a。ログのように「消さずに足していく」用途では必ずこちらを使う。
____ open("memo.txt", "w", encoding="utf-8") as f:
f.write("test")
print("書き込み完了")
出力 == 書き込み完了
ブロックを抜けたときに自動で後始末をしてくれる構文。
with
with を使わない open() は close() を自分で呼ぶ必要があり、途中でエラーが起きると閉じ忘れる。PY10の finally を自動化した仕組みだと考えるとよい。
A. 処理が速くなる B. ブロックを抜けると自動でファイルが閉じられる C. 文字化けしなくなる D. 上書きを防げる 選択★☆☆無料
解答 == B
with が肩代わりしてくれる作業は何か。
B
エラーが起きても確実に閉じられる。文字化け対策は encoding、上書き対策はモード選択と、それぞれ別の話。
出力3行。1: りんご / 2: みかん / 3: ぶどう
書き込みは "りんご\nみかん\nぶどう\n"。読むときは for i, line in enumerate(f, 1): で番号を振り、line.strip() で改行を除く。
with open("fruits.txt", "w", encoding="utf-8") as f:
f.write("りんご\nみかん\nぶどう\n")
with open("fruits.txt", encoding="utf-8") as f:
for i, line in enumerate(f, 1):
print(f"{i}: {line.strip()}")
ファイルオブジェクトはそのまま for で回せて、1行ずつ取り出せる。PY05の enumerate がそのまま使える。
with open("data.txt", "w", encoding="utf-8") as f:
f.write("あ\nい\n")
with open("data.txt", encoding="utf-8") as f:
for line in f:
print(line.____())
出力 == あ / い(2行、空行なし)
前後の空白と改行を取り除くメソッド。PY09でも使った。
print(line.strip())
strip() を忘れると print 自身の改行と合わさって1行おきに空行が入る。ファイル読み込みで最も多いつまずき。
A. ファイルが作られない B. 環境によって文字化けやエラーが起きる C. 必ずエラーになる D. 何も変わらない 選択★★☆無料
解答 == B
既定の文字コードはOSによって違う。
B
自分のPCでは動くのに他の人の環境で壊れる、という再現しにくいバグの原因になる。日本語を扱うなら常に指定すると決めておくのが安全。
出力 == 行数:3 / ['A', 'B', 'C'](2行)
内包表記 [line.strip() for line in f] でリストにまとめられる。
with open("lines.txt", "w", encoding="utf-8") as f:
f.write("A\nB\nC\n")
with open("lines.txt", encoding="utf-8") as f:
lines = [line.strip() for line in f]
print(f"行数:{len(lines)}")
print(lines)
PY09の内包表記でファイル全体を一気にリスト化できる。以降はただのリストとして扱えるので、集計も抽出も自由。
出力3行。['名前', '点数'] / ['田中', '82'] / ['鈴木', '95']
import csv して csv.writer(f).writerow(...)。開くときに newline="" を付けるのが作法。読み込みは csv.reader(f) を for で回す。
import csv
with open("score.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(["名前", "点数"])
writer.writerow(["田中", 82])
writer.writerow(["鈴木", 95])
with open("score.csv", encoding="utf-8") as f:
for row in csv.reader(f):
print(row)
書くときは数値でも、読み込むと必ず文字列になる点に注意(82 → "82")。計算する前に int() で変換する必要がある。
4実践シナリオ(5問)
出力3行。[1] 処理開始 ほか
enumerate(messages, 1) で番号を振りながら f.write する。改行 \n を忘れずに。最後は f.read().rstrip() で末尾の余分な改行を除く。
messages = ["処理開始", "データ取得", "処理完了"]
with open("app.log", "w", encoding="utf-8") as f:
for i, m in enumerate(messages, 1):
f.write(f"[{i}] {m}\n")
with open("app.log", encoding="utf-8") as f:
print(f.read().rstrip())
f.write は改行を自動で入れないので \n を自分で書く。print との最大の違いで、全部が1行につながる事故の原因になる。
「合計:366,000円」「平均:122,000円」「件数:3件」の3行。 コーディング★★☆無料
出力3行が完全一致
f.write の中でも f-string がそのまま使える。平均は {x:,.0f} で整数表示。
sales = [128000, 95000, 143000]
with open("report.txt", "w", encoding="utf-8") as f:
f.write(f"合計:{sum(sales):,}円\n")
f.write(f"平均:{sum(sales) / len(sales):,.0f}円\n")
f.write(f"件数:{len(sales)}件\n")
with open("report.txt", encoding="utf-8") as f:
print(f.read().rstrip())
画面に出すだけの print と違い、ファイルに書けば後から見返せる・他人に渡せる。日次バッチの成果物はこうやって残す。
出力4行が完全一致
next(reader) を1回呼ぶとヘッダ行を読み飛ばせる。読み込んだ点数は文字列なので int() で変換する。
import csv
rows = [["名前", "点数"], ["田中", 82], ["鈴木", 95], ["高橋", 67]]
with open("scores.csv", "w", encoding="utf-8", newline="") as f:
csv.writer(f).writerows(rows)
scores = []
with open("scores.csv", encoding="utf-8") as f:
reader = csv.reader(f)
next(reader)
for name, score in reader:
score = int(score)
scores.append(score)
print(f"{name}:{score}点")
print(f"平均:{sum(scores) / len(scores):.1f}点")
ヘッダの読み飛ばしと文字列→数値の変換はCSV処理の必須作業。writerows() を使えば複数行をまとめて書ける。
出力2行が完全一致
存在しないファイルを開くと FileNotFoundError が出る。PY10の try/except で受け止め、except では return None。
def read_safe(path):
try:
with open(path, encoding="utf-8") as f:
return f.read().strip()
except FileNotFoundError:
return None
with open("exists.txt", "w", encoding="utf-8") as f:
f.write("テストデータ")
for path in ["nothing.txt", "exists.txt"]:
content = read_safe(path)
if content is None:
print(f"{path} → ファイルが見つかりません")
else:
print(f"{path} → 内容:{content}")
ファイルは「あるはず」でも無いことがある——手動で消された、パスが違う、まだ生成されていない。ファイル操作とPY10の例外処理は必ずセットで使う。
出力5行。抽出:3件 の後にヘッダ含む4行
header = next(reader) でヘッダを変数に取っておくと、書き出し側で再利用できる。抽出結果はリストに貯めて writerows() でまとめて書く。
import csv
rows = [["名前", "点数"], ["田中", 82], ["鈴木", 45], ["高橋", 91], ["佐藤", 67]]
with open("all.csv", "w", encoding="utf-8", newline="") as f:
csv.writer(f).writerows(rows)
passed = []
with open("all.csv", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader)
for name, score in reader:
if int(score) >= 60:
passed.append([name, score])
with open("passed.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(header)
writer.writerows(passed)
print(f"抽出:{len(passed)}件")
with open("passed.csv", encoding="utf-8") as f:
for row in csv.reader(f):
print(row)
読む → 絞る → 別ファイルに書くという、実務で最も多いCSV処理のパターン。元ファイルを壊さず新しいファイルを作るのが安全な作法。
5仕上げ課題
rows = [
["日付", "商品", "金額"],
["2026-01-05", "ノートPC", "128000"],
["2026-01-08", "マウス", "3200"],
["2026-01-12", "キーボード", "abc"],
["2026-01-15", "ノートPC", "128000"],
["2026-01-20", "モニター", "45000"],
]
仕様:
① rows を "sales.csv" に書き出す
② 読み込んでヘッダを飛ばし、金額が数値に変換できない行はスキップして件数を数える
③ 商品別の合計金額と件数を集計(登場順)
④ 集計結果を "report.txt" に保存し、読み返して表示
⑤ 最後に保存した旨を1行出力
出力仕様(8行):
=== 売上集計レポート ===
ノートPC:256,000円(2件)
マウス:3,200円(1件)
モニター:45,000円(1件)
---
売上合計:304,200円
有効データ:4件 / スキップ:1件
レポートを report.txt に保存しました
出力8行が完全一致
集計はPY07の totals[item] = totals.get(item, 0) + value。不正行はPY10の try/except ValueError → continue でスキップ。レポートは行をリストに貯めて "\n".join(lines) で一気に書き出すと楽。
import csv
rows = [
["日付", "商品", "金額"],
["2026-01-05", "ノートPC", "128000"],
["2026-01-08", "マウス", "3200"],
["2026-01-12", "キーボード", "abc"],
["2026-01-15", "ノートPC", "128000"],
["2026-01-20", "モニター", "45000"],
]
with open("sales.csv", "w", encoding="utf-8", newline="") as f:
csv.writer(f).writerows(rows)
totals = {}
counts = {}
skipped = 0
with open("sales.csv", encoding="utf-8") as f:
reader = csv.reader(f)
next(reader)
for date, item, amount in reader:
try:
value = int(amount)
except ValueError:
skipped += 1
continue
totals[item] = totals.get(item, 0) + value
counts[item] = counts.get(item, 0) + 1
lines = ["=== 売上集計レポート ==="]
for item, total in totals.items():
lines.append(f"{item}:{total:,}円({counts[item]}件)")
lines.append("---")
lines.append(f"売上合計:{sum(totals.values()):,}円")
lines.append(f"有効データ:{sum(counts.values())}件 / スキップ:{skipped}件")
with open("report.txt", "w", encoding="utf-8") as f:
f.write("\n".join(lines) + "\n")
with open("report.txt", encoding="utf-8") as f:
print(f.read().rstrip())
print("レポートを report.txt に保存しました")
CSVを読む → 不正行を弾く → 集計する → レポートを書き出す。これは実務の定型業務そのもので、毎朝手作業でExcelを開いてやっていた集計が、このスクリプト1本に置き換わる。PY05のループ、PY07の辞書集計、PY10の例外処理、PY11のファイル操作が全部つながった総合問題。ここまで書けたら、Pythonは「勉強するもの」から「仕事に使う道具」に変わっている。