C
Python/ファイル/Lesson 23

ファイルI/O

45分·theory
このチャプター
1/2
Python

ファイルI/O

🎯 このlessonを読み終えたら

このlessonを読み終えると、以下の3つを自信を持って実践できます。

  • pathlib.Pathos.path のモダンな代替
  • with open() コンテキストマネージャー + エンコーディングの明示
  • csvjsonyaml 標準モジュールの活用

学習目標をチェックリストとして手元に置き、すべて答えられるようになったらlessonを閉じてください。

ファイルI/O 6パターン — コード + 実行結果

ファイルの読み書き = データをディスクに保存したり読み込んだりすること。すべてのプログラムの基本。

💻 悪い例 — `os.path` + 手動クローズ
import os

# os.path — 可読性が低い
base = '/data'
filepath = os.path.join(base, 'users', 'data.csv')  # 長くて面倒

# encoding 未指定、手動 close
f = open(filepath)  # プラットフォームのデフォルトエンコーディング (危険)
try:
    content = f.read()
finally:
    f.close()  # with なしで直接管理
💻 良い例 — `pathlib` + `with` 文 + `csv`/`json`
from pathlib import Path
import csv
import json
from typing import Generator

# pathlib — 現代的なパス処理
base = Path('/data')
filepath = base / 'users' / 'data.csv'  # / 演算子で結合

print(filepath.name)        # 'data.csv'
print(filepath.stem)        # 'data'
print(filepath.suffix)      # '.csv'
print(filepath.parent)      # /data/users
print(filepath.exists())    # True/False

# ディレクトリ作成
output_dir = Path('output') / 'reports'
output_dir.mkdir(parents=True, exist_ok=True)  # 中間パスも作成

# テキストファイル読み書き
config_path = Path('config.json')

if config_path.exists():
    text = config_path.read_text(encoding='utf-8')  # 一行で読み込み
config_path.write_text('{"key": "value"}', encoding='utf-8')  # 一行で書き込み

# 大容量ファイルストリーミング処理
def process_large_log(filepath: Path) -> Generator[dict, None, None]:
    """大容量ログファイルをラインごとにストリーミング — メモリ O(1)"""
    with open(filepath, encoding='utf-8', errors='replace') as f:
        for line in f:  # ラインごとに読み込み (全体をロードしない)
            line = line.strip()
            if line and not line.startswith('#'):
                yield {'raw': line, 'length': len(line)}

# CSV 処理
def read_users_csv(filepath: Path) -> list[dict]:
    with open(filepath, encoding='utf-8', newline='') as f:
        reader = csv.DictReader(f)
        return list(reader)

def write_users_csv(filepath: Path, users: list[dict]) -> None:
    with open(filepath, 'w', encoding='utf-8', newline='') as f:
        if users:
            writer = csv.DictWriter(f, fieldnames=users[0].keys())
            writer.writeheader()
            writer.writerows(users)

# JSON 処理
def load_config(filepath: Path) -> dict:
    with open(filepath, encoding='utf-8') as f:
        return json.load(f)

def save_config(filepath: Path, config: dict) -> None:
    with open(filepath, 'w', encoding='utf-8') as f:
        json.dump(config, f, ensure_ascii=False, indent=2)

# glob でファイル検索
for csv_file in Path('data').glob('**/*.csv'):  # 再帰検索
    print(csv_file)

🐍 実際に試してみよう — ファイルI/O

上の概念を実際にコードとして実行してみましょう。値を変えながら動作を自分で確認するのが、最も速い学習方法です。
✏️ Python 코드
📟 コンソール出力
▶ 実行ボタンを押してください
🐍 Pyodideで実際のPythonを実行 — 初回は読み込みに3〜5秒

🤖 AIへのリクエスト例

このlessonの概念を知っていれば、AIに具体的に指示できます。漠然とした「直して」ではなく、語彙を持ったリクエスト — それがトークン節約の出発点です。

  • 「この os.path コードを pathlib に移行して」
  • 「この with open ブロックに適切なエンコーディング (encoding='utf-8') を明示して」

なぜこれがトークンを減らすのか

概念を知らないと、AI の回答を受け取っても 「それって何ですか?」 と再度聞き直す必要があります。その「聞き直し」がトークンを消費します。概念を一度習得しておけば、会話が一回で完結します

先に読むとよい概念: pytest入門
ファイルI/O - Python