ファイル I/O

これまでのプログラムデータはメモリ上にしか存在していませんでした——プログラムを閉じるとデータは失われます。ファイル I/O により、プログラムはデータをディスクに保存し、次回起動時に読み戻すことができるようになります。これは実用的なアプリケーションにとって基本的な機能です。


1. ファイルを開く/閉じる

基本的なファイル操作は 3 つのステップです:開く → 読み書き → 閉じる。

例:ファイルを手動で開く/閉じる

PYTHON
# ファイルに書き込む
file = open("hello.txt", "w", encoding="utf-8")
file.write("Hello, World!")
file.close()

# ファイルから読み取る
file = open("hello.txt", "r", encoding="utf-8")
content = file.read()
file.close()

print(content)              # Hello, World!
▶ 試してみよう
⚠️ 注意:必ず close() を忘れずに! 開かれたファイルはシステムリソースを消費します。閉じ忘れると、ファイル破損やリソース枯渇の原因になります。しかし心配はいりません——次のセクションでより良い方法を紹介します。


2. with 文(コンテキストマネージャー)

with 文はコードブロックの終了時に自動的にファイルを閉じ、close() を呼び出す必要がありません:

例:with を使った安全なファイル I/O

PYTHON
# 書き込み
with open("hello.txt", "w", encoding="utf-8") as f:
    f.write("Hello, World!")

# 読み取り
with open("hello.txt", "r", encoding="utf-8") as f:
    content = f.read()

print(content)
▶ 試してみよう
💡 ファイル操作には常に with を使いましょう。 これが最も安全で、最も Python らしい方法です——コードブロック内で例外が発生しても、ファイルは正しく閉じられます。


3. ファイルオープンモード

open() の 2 番目のパラメータがモードです:

モード 意味 ファイルが存在する場合 ファイルが存在しない場合
"r" 読み取り(デフォルト) 通常読み取り エラー
"w" 書き込み クリアして書き込み 作成
"a" 追記 末尾に追加 作成
"x" 排他的作成 エラー 作成
"r+" 読み書き 読み書き可能 エラー

例:異なるファイルオープンモード

PYTHON
# "w" — 書き込み(クリアして書き直し)
with open("test.txt", "w", encoding="utf-8") as f:
    f.write("First line\n")
    f.write("Second line\n")

# "a" — 追記
with open("test.txt", "a", encoding="utf-8") as f:
    f.write("Third line\n")

# "r" — 読み取り
with open("test.txt", "r", encoding="utf-8") as f:
    print(f.read())
▶ 試してみよう

出力:

TEXT
First line
Second line
Third line

4. ファイル読み取りの方法

例:ファイルを読み取る 3 つの方法

PYTHON
# ファイルの内容を想定:
# First line
# Second line
# Third line

# 方法 1:read() — 一度にすべて読み取り
with open("test.txt", "r", encoding="utf-8") as f:
    content = f.read()
print(content)

# 方法 2:readlines() — リストとして読み取り
with open("test.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
print(lines)                # ['First line\n', 'Second line\n', 'Third line\n']

# 方法 3:1 行ずつ(推奨)
with open("test.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())  # strip() で改行文字を除去
▶ 試してみよう

例:ファイルバックアップツール(難易度 ⭐⭐)

PYTHON
def backup_file(filename):
    """ファイルのバックアップコピーを作成"""
    try:
        with open(filename, "r", encoding="utf-8") as f:
            content = f.read()
        
        backup_name = filename + ".bak"
        with open(backup_name, "w", encoding="utf-8") as f:
            f.write(content)
        
        print(f"Backup created: {backup_name}")
    except FileNotFoundError:
        print(f"File {filename} does not exist!")

backup_file("test.txt")
▶ 試してみよう

5. CSV ファイルの読み書き

CSV(カンマ区切り値)は最も一般的なデータ交換形式です。Python には組み込みの csv モジュールがあります:

例:CSV ファイル I/O

PYTHON
import csv

# CSV 書き込み
data = [
    ["Name", "Age", "City"],
    ["Zhang San", 25, "Beijing"],
    ["Li Si", 30, "Shanghai"],
    ["Wang Wu", 22, "Guangzhou"],
]

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

# CSV 読み取り
with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
▶ 試してみよう

DictReader/DictWriter の使用(より直感的)

例:CSV 用 DictReader/DictWriter

PYTHON
import csv

# 書き込み
data = [
    {"name": "Zhang San", "age": 25, "city": "Beijing"},
    {"name": "Li Si", "age": 30, "city": "Shanghai"},
]

with open("students_dict.csv", "w", newline="", encoding="utf-8") as f:
    fieldnames = ["name", "age", "city"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()       # ヘッダーを書き込み
    writer.writerows(data)     # データ行を書き込み

# 読み取り
with open("students_dict.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['name']} — {row['age']} years old, from {row['city']}")
▶ 試してみよう

6. パス処理

ファイルパスの処理には os.path または pathlib を使用します——文字列連結より安全です:

例:os.path によるパス処理

PYTHON
import os

# 現在のディレクトリを取得
print(os.getcwd())          # /project

# パスを結合(区切り文字を自動処理)
path = os.path.join("data", "files", "test.txt")
print(path)                 # data/files/test.txt

# パスの存在確認
print(os.path.exists("test.txt"))          # True/False
print(os.path.isfile("test.txt"))          # ファイルか?
print(os.path.isdir("data"))               # ディレクトリか?

# ファイル情報を取得
print(os.path.getsize("test.txt"))         # ファイルサイズ(バイト)

# ディレクトリ内容の一覧
for f in os.listdir("."):
    print(f)
▶ 試してみよう

推奨:pathlib(Python 3.4+)

例:pathlib によるパス操作

PYTHON
from pathlib import Path

# パスを作成
p = Path("data/files/test.txt")

# パス情報
print(p.name)               # test.txt(ファイル名)
print(p.stem)               # test(拡張子なし)
print(p.suffix)             # .txt(拡張子)
print(p.parent)             # data/files(親ディレクトリ)

# ファイルの読み書き(簡潔)
p = Path("hello.txt")
p.write_text("Hello, World!", encoding="utf-8")
content = p.read_text(encoding="utf-8")
print(content)              # Hello, World!

# 再帰的走査
for py_file in Path(".").rglob("*.py"):
    print(py_file)
▶ 試してみよう
💡 Python 3.4+ では pathlib がパス処理の推奨方法です。 os.path よりもオブジェクト指向で直感的です。新しいプロジェクトでは pathlib を使用してください。


よくあるユースケース


❓ よくある質問

Q 毎回 encoding="utf-8" と書く必要がありますか?
A 日本語環境では、毎回指定することを強くお勧めします。Python のデフォルトエンコーディングは OS によって異なります——Windows は shift_jis または utf-8、macOS/Linux は utf-8。指定しないと、Windows で日本語テキストファイルを処理するときに文字化けが発生する可能性があります。クロスプラットフォームの安心のためにエンコーディングを指定する習慣をつけましょう。
Q "w" モードは既存のファイル内容を消去します。誤って上書きしないようにするには?
A "x" モード(排他作成)を使います——ファイルが既に存在する場合、消去する代わりにエラーを発生させます。または os.path.exists() で事前に確認します。データは貴重です——ファイルに書き込む前にはよく考えましょう。
Q 非常に大きなファイル(数百 MB)を読むには?
A read()readlines() は使わないでください——ファイル全体をメモリに読み込みます。for line in file: を使って 1 行ずつ読み取り、一度に 1 行だけを最小限のメモリで処理します。または、read(1024) で一度に特定のバイト数を読み取ることもできます。

📖 まとめ


📝 練習問題

  1. 基本(難易度 ⭐):ユーザーの名前と年齢を受け付け、users.txt ファイルに保存するプログラムを書いてください(1 ユーザー 1 行、形式:name,age)。実行するたびに新しいレコードを追加し、既存データを上書きしないでください。

  2. 中級(難易度 ⭐⭐):前の練習問題の users.txt ファイルを読み取り、各行を解析し、ユーザーの平均年齢を計算して出力するプログラムを書いてください。ヒント: split(",") で解析、int() で年齢を変換。

  3. 挑戦(難易度 ⭐⭐⭐):「簡易ノート帳」プログラムを書いてください。機能:add:title|content でメモを追加(notes.csv に追記)、list ですべてのメモを表示、search:keyword でメモを検索。CSV 形式で保存(フィールド:タイトル、内容、作成時刻)。ヒント: 現在のタイムスタンプには datetime.now() を使用。

100%