閉じる

【Python】openとファイルモード入門:r・w・aの違いと安全な使い方

Pythonでファイルを扱うとき、必ず登場するのがopen関数とファイルモードです。

特にr・w・aの違いを正しく理解していないと、大事なファイルを上書きして消してしまうなど危険な失敗につながります。

本記事では、基本のファイルモードから、安全な書き方、実務で役立つテクニックまで、初心者の方にも分かりやすく丁寧に解説します。

Pythonのopen関数とは

openとは

Pythonでファイルを読み書きする入口になるのがopen関数です。

ファイルはパソコンのストレージ上に保存されていますが、Pythonからそのファイルにアクセスするには、まずopenを使って「ファイルオブジェクト」を取得します。

このファイルオブジェクトを通して、次のような操作が行えます。

  • 中身の読み込み
  • データの書き込み
  • 書き込み位置の移動
  • ファイルを閉じる

openは「ファイルのドアを開ける関数」だとイメージすると理解しやすくなります。

ドアを開けたら、最後に必ずcloseしてドアを閉める必要があります。

この閉じ忘れを防ぐための方法も、後半で詳しく解説します。

openの基本構文と引数

open関数の基本的な書き方は次のようになります。

Python
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

日常的によく使うのはfilemodeencodingの3つです。

特にmode(ファイルモード)が本記事の主役です。

よく使う引数

  • file
    開きたいファイルのパス(場所)を文字列で指定します。例として"data.txt"のように書きます。
  • mode
    ファイルをどういう目的で開くかを指定します。
    代表的なものは次の通りです。
    • "r": 読み込み専用
    • "w": 新規作成または上書き
    • "a": 追記
    • "rb": バイナリ読み込み
    • "r+": 読み書き両方
  • encoding
    テキストファイルの文字コードを指定します。日本語を扱うときは“utf-8”を指定するのが一般的です。

最もシンプルな使用例

Python
# ファイルを読み込みモードで開く例
f = open("sample.txt", "r", encoding="utf-8")

# ファイルの内容を読み込む
content = f.read()
print(content)

# ファイルを閉じる
f.close()

ファイルモードの種類と意味

Pythonのファイルモードは、「何をするためにファイルを開くのか」を指定するためのものです。

理解しやすくするために、まずは最もよく使うrwaから整理し、そのあとでb+などの追加指定について説明します。

読み込みモードrの使い方と注意点

rモードの基本

"r"読み込み専用モードです。

主な特徴は次のとおりです。

  • 既存のファイルを読むために使う
  • ファイルが存在しないとFileNotFoundErrorが発生する
  • 原則としてファイルに書き込みはできない

rモードの基本的な例

Python
# sample.txt の内容を1行ずつ読み込んで表示する例
with open("sample.txt", "r", encoding="utf-8") as f:
    # ファイルオブジェクト f はイテレータとして1行ずつ取得できる
    for line in f:
        # 行末の改行を削除してから表示
        print(line.rstrip())

この例ではwith構文を使っていますが、詳細は後ほど説明します。

ここではファイルが必ず正しく閉じられる書き方だと理解しておけば十分です。

rモードの注意点

存在しないファイルをrで開こうとするとエラーになる点が重要です。

たとえば次のコードは、ファイルがない場合にエラーで止まってしまいます。

Python
# sample.txt が存在しないと FileNotFoundError になる例
with open("sample.txt", "r", encoding="utf-8") as f:
    print(f.read())

このような場合は、例外処理や存在チェックを組み合わせて使う必要があります。

これも後ほど詳しく解説します。

書き込みモードwの使い方と注意点

wモードの基本

"w"書き込み専用モードで、既存の内容をすべて消してから書き込むのが特徴です。

  • ファイルが存在しない場合: 新しく作成される
  • ファイルが存在する場合: 中身が空になってから書き込まれる(上書き)
  • 原則として読み込みはできない

wモードでの書き込み例

Python
# sample.txt にテキストを書き込む例
with open("sample.txt", "w", encoding="utf-8") as f:
    f.write("1行目のテキストです。\n")
    f.write("2行目のテキストです。\n")

このコードを実行すると、sample.txtが存在していても中身はすべて消え、2行のテキストだけが保存されます。

wモードの危険ポイント

wモードは非常に強力で危険です。

特に次の点に注意が必要です。

  • 間違ったファイル名を指定すると、大事なファイルを上書きしてしまう
  • 元の内容は基本的に復元できない(バックアップがない限り)

安全のためには、後述する存在チェックバックアップの作成を組み合わせることが重要です。

追記モードaの使い方と注意点

aモードの基本

"a"追記専用モードです。

既存の内容を残したまま、ファイルの末尾に書き足すときに使用します。

  • ファイルが存在しない場合: 新しく作成される
  • ファイルが存在する場合: 末尾にデータを追加する
  • 原則として読み込みはできない

aモードの書き込み例

Python
# ログファイルに1行追記する例
with open("log.txt", "a", encoding="utf-8") as log_file:
    log_file.write("アプリケーションを起動しました。\n")

すでにlog.txtがあれば最後に1行追加され、なければ新しく作成されます。

ログファイルや履歴の保存などに便利です。

aモードの注意点

追記モードは上書きしないので安全そうに見えますが、次のような注意点があります。

  • 間違ったファイルに追記しても気づきにくい
  • 行末に改行を入れ忘れると、前の行とつながってしまう
  • 非常に大きなファイルに延々と追記し続けると、容量が肥大化する

定期的にログをローテーションするなど、運用面の工夫も必要になります。

文字列専用tモードとバイナリbモード

ファイルモードにはtbという補助指定があります。

  • t: テキストモード(文字列として扱う)
  • b: バイナリモード(バイト列として扱う)

Pythonではデフォルトがテキストモード(t)なので、通常は明示的に"t"を書く必要はありません。

一方、画像ファイルやPDF、zipなどテキストではないファイルを扱うときは"b"を付けます。

テキストモード(t)の例

Python
# 明示的にテキストモードを指定した例("rt" は "r" と同じ意味)
with open("note.txt", "rt", encoding="utf-8") as f:
    print(f.read())

バイナリモード(b)の例

Python
# 画像ファイルをバイナリモードで読み込んでコピーする例
with open("input.png", "rb") as src, open("output.png", "wb") as dst:
    data = src.read()
    dst.write(data)

バイナリモードでは文字コードの概念がなくencoding引数も使いません。

データはbytes型として扱われます。

読み書きモードr+・w+・a+の違い

+が付いたモードは、読み書き両方を行うモードです。

ただし、挙動が少し複雑なので、違いを表で押さえておくと理解しやすくなります。

モード既存ファイルの扱い読み込み書き込み開始位置主な用途
r+必須(なければエラー)先頭既存内容を読みつつ一部書き換え
w+あっても中身を消す先頭(中身は空)新規作成して読み書き両方
a+あれば末尾に追記末尾既存ログを読みつつ追記

r+ の例

Python
# ファイルの先頭部分だけを書き換える例
with open("data.txt", "r+", encoding="utf-8") as f:
    original = f.read()
    # 読み込んだ後、先頭に戻る
    f.seek(0)
    f.write("先頭を書き換えました。\n")

w+ の例

Python
# 新しいファイルを作ってから読み書きする例
with open("new_data.txt", "w+", encoding="utf-8") as f:
    f.write("最初の内容です。\n")
    # ファイルの先頭に戻して読み込む
    f.seek(0)
    print(f.read())

a+ の例

Python
# 末尾に追記しつつ、全体も読み込める例
with open("log.txt", "a+", encoding="utf-8") as f:
    f.write("新しいログを追加しました。\n")
    # 読み込みのために先頭に戻る
    f.seek(0)
    print(f.read())

r+・w+・a+は、ファイル位置(カーソル)の扱いが重要です。

必要に応じてseekで位置を移動しながら使うとよいです。

安全なファイル操作の書き方

with構文を使った安全なopenの書き方

ファイルを開いたら、必ず close する必要があります。

close を忘れると、次のような問題が発生する可能性があります。

  • ファイルがロックされたままになり、他のプログラムから触れない
  • 書き込みが完全に完了せず、データが失われる
  • 多数のファイルを開きっぱなしにしてリソースを消費する

Pythonではwith構文を使うことで、自動的に close してくれる書き方ができます。

with 構文の基本形

Python
with open("sample.txt", "r", encoding="utf-8") as f:
    data = f.read()
    print(data)
# ここに来た時点で、f は自動的に close されている

ブロック(インデント部分)を抜けた瞬間に自動で closeされるため、エラーが途中で発生しても安心です。

ファイルを扱うときは、原則としてwith open(...)を使うことをおすすめします。

ファイルが存在しない場合のエラー処理

存在しないファイルを"r""r+"で開こうとすると、FileNotFoundErrorが発生します。

これを安全に処理するには、例外処理(try-except)を使います。

Python
file_path = "missing.txt"

try:
    with open(file_path, "r", encoding="utf-8") as f:
        data = f.read()
        print(data)
except FileNotFoundError:
    print(f"{file_path} が見つかりません。新規作成します。")
    # 必要に応じて新規ファイルを作成
    with open(file_path, "w", encoding="utf-8") as f:
        f.write("新しく作成したファイルです。\n")

このようにtryexceptで囲むことで、エラー発生時にもプログラムを安全に継続できます。

上書き・削除を避けるためのチェック方法

誤ってファイルを上書きしないためには、書き込み前のチェックが重要です。

特に"w""w+"を使うときは注意が必要です。

os.path.exists を使ったチェック

Python
import os

file_path = "important.txt"

if os.path.exists(file_path):
    print(f"{file_path} はすでに存在します。上書きしてもよいか確認してください。")
else:
    with open(file_path, "w", encoding="utf-8") as f:
        f.write("新しい重要ファイルです。\n")

このようにos.path.exists事前に存在を確認しておくことで、意図しない上書きを防止できます。

バックアップを取ってから書き込む例

Python
import os
import shutil

file_path = "config.txt"

if os.path.exists(file_path):
    backup_path = file_path + ".bak"
    shutil.copy(file_path, backup_path)
    print(f"バックアップを {backup_path} に作成しました。")

with open(file_path, "w", encoding="utf-8") as f:
    f.write("新しい設定内容を書き込みました。\n")

書き込み前にバックアップを自動作成しておくと、万が一のときに復元が可能になります。

文字コードencoding指定と文字化け対策

日本語を扱うときのトラブルで多いのが文字化けです。

その多くはencoding の指定ミスが原因です。

基本の対策

  • 可能な限りUTF-8を使う
  • openを使うときはencoding="utf-8"を明示する
  • 既存のファイルの文字コードが不明な場合は、エディタやツールで確認する
Python
# UTF-8 でファイルを開く例
with open("message.txt", "r", encoding="utf-8") as f:
    text = f.read()
    print(text)

エラー時の対処(encoding と errors)

Python
# 読み込み時に文字化けやエラーが出る場合の例
with open("legacy.txt", "r", encoding="cp932", errors="replace") as f:
    text = f.read()
    print(text)

errors="replace"を指定すると、変換できない文字を「?」などで置き換えて読み込むため、エラーで止まることを避けられます。

ただし、データの一部が失われる可能性がある点には注意が必要です。

よくある疑問と実践テクニック

相対パス・絶対パスの指定方法

ファイルの場所を指定する方法には絶対パス相対パスがあります。

絶対パス

ストレージのルートから始まる、ファイルまでの完全な道筋です。

  • Windows例: "C:/Users/user/project/data.txt"
  • macOS/Linux例: "/Users/user/project/data.txt"
Python
# 絶対パスを指定する例
path = "C:/Users/user/project/data.txt"
with open(path, "r", encoding="utf-8") as f:
    print(f.read())

相対パス

現在の作業ディレクトリ(カレントディレクトリ)からの相対的な位置で指定する方法です。

  • 同じフォルダ: "data.txt"
  • サブフォルダ: "data/input.txt"
  • 1つ上の階層: "../config/settings.ini"
Python
# 相対パスを指定する例
with open("data/input.txt", "r", encoding="utf-8") as f:
    print(f.read())

スクリプトの場所を基準にしたい場合は、__file__pathlibを使う方法が便利です。

Python
from pathlib import Path

# このスクリプトファイルの場所を基準に paths/data.txt を開く
base_dir = Path(__file__).parent
file_path = base_dir / "paths" / "data.txt"

with open(file_path, "r", encoding="utf-8") as f:
    print(f.read())

WindowsとMacでのパス指定の違い

WindowsとmacOS/Linuxでは、パスの区切り文字が異なります。

  • Windows: バックスラッシュ\
  • Mac / Linux: スラッシュ/

ただし、Pythonの文字列では\がエスケープシーケンスとぶつかるため、原則として/を使うか、pathlibを利用するのが安全です。

危険な例(バックスラッシュをそのまま使用)

Python
# \n が改行として解釈されてしまう危険な書き方
path = "C:\new_folder\data.txt"  # NG

安全な書き方の例

Python
# 1) スラッシュ / を使う
path = "C:/new_folder/data.txt"

# 2) raw 文字列を使う
path = r"C:\new_folder\data.txt"

# 3) pathlib を使う(推奨)
from pathlib import Path

path = Path("C:/new_folder/data.txt")

pathlib を使うと OS の違いを意識せずに済むので、複雑なパス操作をする場合に特に便利です。

大きなファイルを扱うときの注意点

大きなファイル(例えば数百MB〜数GB)を扱う場合、一度に全て読み込むとメモリ不足を起こす危険があります。

そのため、データを少しずつ読み込む工夫が必要です。

行ごとに読み込む

Python
# ファイルを1行ずつ処理する例(メモリ効率が良い)
with open("large_file.txt", "r", encoding="utf-8") as f:
    for line in f:
        # 各行を順番に処理
        process_line = line.strip()
        # ここで必要な処理を行う

ファイルオブジェクト自体がイテレータとして動作するため、for ループで1行ずつ読み取るのが簡単で効率的です。

固定サイズのチャンクで読み込む

Python
# 1MBずつ読み込む例
chunk_size = 1024 * 1024  # 1MB

with open("large_binary.dat", "rb") as f:
    while True:
        chunk = f.read(chunk_size)
        if not chunk:
            break  # 読み込み完了
        # chunk に対して処理を行う

このように一定サイズずつ読み込むことで、どれだけ大きなファイルでも安定して処理できます。

まとめ

本記事では、Pythonのopen関数とファイルモード(r・w・a)を中心に、テキスト/バイナリモード、読み書きモードの違い、そして安全にファイルを扱うための実践的なテクニックを解説しました。

特にwモードの上書きリスクやencodingの指定、with構文による自動クローズは、実務でのトラブルを避けるうえで非常に重要です。

ここで紹介した考え方とサンプルをベースに、実際のプロジェクトでも安心してファイル操作が行えるよう練習してみてください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!