ファイル I/O
これまでのプログラムデータはメモリ上にしか存在していませんでした——プログラムを閉じるとデータは失われます。ファイル I/O により、プログラムはデータをディスクに保存し、次回起動時に読み戻すことができるようになります。これは実用的なアプリケーションにとって基本的な機能です。
1. ファイルを開く/閉じる
基本的なファイル操作は 3 つのステップです:開く → 読み書き → 閉じる。
例:ファイルを手動で開く/閉じる
# ファイルに書き込む
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
# 書き込み
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+" |
読み書き | 読み書き可能 | エラー |
例:異なるファイルオープンモード
# "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())
出力:
First line
Second line
Third line
4. ファイル読み取りの方法
例:ファイルを読み取る 3 つの方法
# ファイルの内容を想定:
# 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() で改行文字を除去
例:ファイルバックアップツール(難易度 ⭐⭐)
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
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
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 によるパス処理
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 によるパス操作
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)
pathlib がパス処理の推奨方法です。 os.path よりもオブジェクト指向で直感的です。新しいプロジェクトでは pathlib を使用してください。
よくあるユースケース
- データ永続化:プログラムデータをファイルに保存し、次回起動時に復元
- ログ記録:プログラムの実行時情報をログファイルに追記
- 設定管理:設定ファイル(
.ini、.json、.env)を読み取り - データインポート/エクスポート:CSV 形式で Excel/データベースとデータ交換
- バッチファイル処理:ディレクトリを走査し、ファイル内容を一括変更またはリネーム
❓ よくある質問
encoding="utf-8" と書く必要がありますか?shift_jis または utf-8、macOS/Linux は utf-8。指定しないと、Windows で日本語テキストファイルを処理するときに文字化けが発生する可能性があります。クロスプラットフォームの安心のためにエンコーディングを指定する習慣をつけましょう。"w" モードは既存のファイル内容を消去します。誤って上書きしないようにするには?"x" モード(排他作成)を使います——ファイルが既に存在する場合、消去する代わりにエラーを発生させます。または os.path.exists() で事前に確認します。データは貴重です——ファイルに書き込む前にはよく考えましょう。read() や readlines() は使わないでください——ファイル全体をメモリに読み込みます。for line in file: を使って 1 行ずつ読み取り、一度に 1 行だけを最小限のメモリで処理します。または、read(1024) で一度に特定のバイト数を読み取ることもできます。📖 まとめ
- ファイル操作の 3 ステップ:
open()→ 読み書き →close() with文はファイルクローズを自動管理——最も安全な方法- モード:
"r"読み取り、"w"書き込み、"a"追記 - 読み取り方法:
read()全文、readlines()リスト、for line in f行ごと csvモジュールで CSV ファイル I/O。DictReader/DictWriterをサポートos.pathとpathlibでファイルパス処理。pathlibがよりモダン- 常に
encoding="utf-8"を指定
📝 練習問題
-
基本(難易度 ⭐):ユーザーの名前と年齢を受け付け、
users.txtファイルに保存するプログラムを書いてください(1 ユーザー 1 行、形式:name,age)。実行するたびに新しいレコードを追加し、既存データを上書きしないでください。 -
中級(難易度 ⭐⭐):前の練習問題の
users.txtファイルを読み取り、各行を解析し、ユーザーの平均年齢を計算して出力するプログラムを書いてください。ヒント:split(",")で解析、int()で年齢を変換。 -
挑戦(難易度 ⭐⭐⭐):「簡易ノート帳」プログラムを書いてください。機能:
add:title|contentでメモを追加(notes.csvに追記)、listですべてのメモを表示、search:keywordでメモを検索。CSV 形式で保存(フィールド:タイトル、内容、作成時刻)。ヒント: 現在のタイムスタンプにはdatetime.now()を使用。



