Python WebAcademy Blog

Pythonのファイル読み書きとは?open()とwith文の基本を初心者向けに解説

|

Pythonでテキストファイルを読み書きする方法を、IT初心者向けにやさしく解説します。open関数の書き方、モードの選び分け、with文が必要な理由、読み込みの3つのやり方、追記と上書きの違い、encodingを指定して文字化けを防ぐ方法、そしてPython 3.15で変わる既定のエンコーディングまで、動かせるコードを並べながら順番に紹介します。

Pythonの基本文法を覚えて、簡単なプログラムが動くようになってきた。それなのに、実行が終わると結果がきれいさっぱり消えてしまう。

画面に表示された数字は、ウィンドウを閉じた瞬間になくなります。せっかく集計した結果を明日も使いたいとき、どうすればいいのでしょうか。

答えはファイルです。プログラムの外にデータを残す方法として、いちばん手軽で確実なのがファイルへの読み書きになります。

この記事では、Pythonでテキストファイルを扱う基本を順番に追いかけます。初心者がほぼ必ずぶつかる文字化けと上書き事故も、あわせて片づけていきましょう。

ファイルを開くとは、どういうことなのか

日常会話で言うファイルを開くは、アイコンをダブルクリックして中身を見ることを指します。プログラムの世界では、もう少し具体的な意味を持っています。

Pythonがファイルを開くとき、裏側ではOSに対して、このファイルを使わせてくださいという申請が飛んでいます。OSはそれを受けて、読み書きのための通り道を用意します。

この通り道には数に限りがあります。だから使い終わったら、閉じますと伝えて返す必要があるわけです。

開いて、読み書きして、閉じる。この3拍子がファイル操作の全体像で、Pythonのコードもきれいにこの順番どおりに並びます。

open関数は、名前とモードとencodingで決まる

ファイルを開く役目を持つのがopenという組み込み関数です。引数はたくさんありますが、日常的に使うのは最初の3つだけと考えて構いません。

まずは、いちばん短い形を見てみましょう。

f = open("memo.txt", "r", encoding="utf-8")
print(f.read())
f.close()

1つ目がファイル名、2つ目がモード、3つ目が文字の解釈方法です。最後のcloseで通り道を返しています。

このコードは動きますが、実務で書くことはまずありません。理由はあとで説明しますが、先にモードとencodingを押さえておきましょう。

モードは、読むのか書くのかを伝える合図

モードは短いアルファベットで指定します。似た文字が並ぶので、最初は混乱しやすいところです。

よく使うものを表にまとめました。

モード 意味 ファイルが無いとき 既存の中身
r 読み込み専用(既定値) エラーになる そのまま
w 書き込み 新しく作る すべて消える
a 追記 新しく作る 残る(末尾に追加)
x 新規作成のみ 新しく作る エラーになる
rb / wb バイナリで読み書き rはエラー、wは作成 wは消える

覚え方はシンプルで、readのr、writeのw、appendのaです。モードを省略するとrになるので、読むだけなら指定しなくても動きます。

この表でいちばん気をつけたいのは、wが既存の中身を消してしまうことです。追記のつもりでwを渡してしまい、前日までのログが空になった。私は10年ほどエンジニアとして開発に関わってきましたが、この事故は新人時代に自分でやりましたし、他人のコードでも何度か見ています。

encodingを省略すると、環境で結果が変わる

encodingは、ファイルの中のバイト列をどの文字として読むかの指定です。日本語を扱うなら、ここを省略してはいけません。

なぜなら、省略したときの既定値は動かす環境によって変わるからです。Linuxやmacではだいたいutf-8になり、日本語版Windowsではcp932になることがあります。

同じコードが自分のMacでは動くのに、同僚のWindowsでは文字化けする。原因の8割はencodingの省略だと思ってよいくらい、定番のトラブルです

対策は簡単で、テキストを開くときは必ずencoding="utf-8"と書くだけ。たったこれだけで、環境差の悩みがほとんど消えます。

with文を使えば、閉じ忘れが起きない

さきほどのコードにはcloseがありました。実は、あれを手で書く方法には弱点があります。

readの途中でエラーが起きると、closeまで到達しません。ファイルが開きっぱなしになり、Windowsでは他のプログラムから触れなくなることもあります。

そこで登場するのがwith文です。ブロックを抜けるときに、エラーが起きたかどうかに関係なく自動で閉じてくれます。

with open("memo.txt", encoding="utf-8") as f:
    print(f.read())
# ここに来た時点で、fはもう閉じている

closeが消えて、行数も減りました。Pythonでファイルを開くときは、常にwith文を使うと覚えてしまって構いません。

この自動で後始末をする仕組みは、コンテキストマネージャーと呼ばれています。仕組みそのものが気になる方は、こちらもどうぞ。【関連記事】pythonのコンテキストマネージャーって何?詳しく解説します!

読み込みには、3つのやり方がある

ファイルを読む書き方はひとつではありません。データの量と、やりたいことで選び分けます。

3つの方法を、使いどころとあわせて並べてみます。

書き方 返ってくるもの 向いている場面
f.read() 全体が1つの文字列 小さいファイルをまとめて扱う
f.readlines() 1行ずつのリスト 行数を数える、あとで並べ替える
for line in f 1行ずつ順番に 大きいファイル、ログの走査

readとreadlinesは、ファイル全体をメモリに載せます。数KBのメモなら問題ありませんが、数GBのログでやると一気にメモリが埋まります。

一方でforを使う書き方は、1行ずつ読んでは捨てるので、ファイルがどれだけ大きくてもメモリは増えません。迷ったらforを選んでおくと安全です。

実際に動かしてみましょう。

with open("access.log", encoding="utf-8") as f:
    for i, line in enumerate(f, start=1):
        line = line.rstrip("\n")
        if "ERROR" in line:
            print(f"{i}行目: {line}")

rstripで末尾の改行を落としているのがポイントです。ファイルから読んだ行には改行文字がくっついたままなので、そのまま表示すると余計な空行が出ます。

書き込みは、上書きと追記を意識して選ぶ

書くときも同じくwith文を使います。違うのはモードだけです。

まずは新しくファイルを作って、中身を入れてみます。

lines = ["りんご", "みかん", "ぶどう"]

with open("fruits.txt", "w", encoding="utf-8") as f:
    for name in lines:
        f.write(name + "\n")

with open("fruits.txt", "a", encoding="utf-8") as f:
    f.write("もも\n")

前半がwで新規作成、後半がaで追記です。writeはprintと違って改行を自動で付けないので、自分で\nを足す必要があります。

ここを忘れると、りんごみかんぶどうと1行にくっついて出てきます。よくあるつまずきなので、書き込みのときは改行を意識してください。

改行そのものの扱いが不安な方は、こちらの記事もあわせてどうぞ。【関連記事】Pythonの改行を初心者向けに解説!print・文字列・ファイル出力で迷わない基本

文字化けが起きたときに、どこを疑うか

encodingを指定していても、文字化けやエラーに出会うことはあります。多くは、読む側と書いた側の食い違いが原因です。

Excelから出したファイルがcp932で保存されているのに、utf-8で読もうとした。この場合はUnicodeDecodeErrorという例外が出ます。

エラーになるだけまだ親切で、いちばん厄介なのは化けた文字がそのまま通ってしまうケースです。データベースに入るまで誰も気づかない、という事態になりかねません。

対処の順番を整理しておきます。

症状 疑うところ 対応
UnicodeDecodeErrorが出る 読むときのencodingが違う cp932shift_jis を試す
先頭に見慣れない文字が付く BOM付きutf-8 encoding="utf-8-sig" にする
Excelで開くと化ける 書くときのencoding 書き出しを utf-8-sig にする

utf-8-sigは、日本の実務でかなり出番があります。ExcelはBOMが無いutf-8のcsvを素直に読んでくれないことがあるためです。

このあたりはcsvを扱うときに集中して出てくる話題なので、表データを読み書きする予定がある方はこちらもどうぞ。【関連記事】Pythonのcsvモジュールとは?表データの読み書きと文字化けの防ぎ方を初心者向けに解説

テキストで開くか、バイナリで開くか

ここまではすべてテキストモードの話でした。モードにbを付けると、バイナリモードに切り替わります。

違いは、Pythonが中身を文字として解釈するかどうかです。テキストモードはバイト列を文字列に変換し、バイナリモードは変換せずbytes型のまま渡します。

画像やPDF、zipのようなファイルは、文字として解釈しようとすると壊れます。だから画像をコピーするようなコードでは、必ずbを付けます。

with open("logo.png", "rb") as src:
    data = src.read()

with open("copy.png", "wb") as dst:
    dst.write(data)

バイナリモードではencodingを指定できません。文字として解釈しない以上、指定する意味がないからです。

判断はシンプルで、人が読める中身ならテキスト、それ以外はバイナリと考えておけば大きく外しません。JSONのように構造を持ったテキストは、専用のモジュールに任せるのが定石です。【関連記事】PythonでJSONデータの扱いをマスター!API連携に必須のjsonモジュールの使い方

Python 3.15から、encodingの既定が変わる

ここまでencodingを必ず書きましょうと繰り返してきました。実は、この事情は今後ゆるやかに変わっていきます。

PEP 686という提案が承認され、Python 3.15からはUTF-8モードが既定で有効になります。つまり、encodingを省略したときの動きがどの環境でもutf-8に揃うわけです。

Python 3.15は2026年10月1日にリリース予定です。長らく日本のPython開発者を悩ませてきた環境差が、ようやく標準の側で解消されることになります。

とはいえ、しばらくは古いバージョンも現役です。明示的にencodingを書く習慣は、これからも持っておいて損はありません

なお、encodingを省略している箇所を洗い出したいときは、実行時にオプションを付ける方法があります。

python -X warn_default_encoding your_script.py

こうするとEncodingWarningという警告が出て、指定を省いた行が見つかります。3.15への移行前に一度かけてみると、直すべき場所が一目でわかります。3.15の変更点全体を知りたい方は、こちらもどうぞ。【関連記事】Python 3.15の新機能を先取り解説!lazy importやfrozendictで何が変わるのか

まとめ

ファイルの読み書きは、Pythonを実務で使い始めるときの最初の関門です。押さえるところは多くありません。

with文で開いて、モードを正しく選び、encodingを明示する。この3点さえ守れば、初心者がぶつかる事故のほとんどは避けられます。

私自身、10年たった今でもwとaの取り違えには神経を使っています。上書きは一瞬で終わり、取り返しがつかないからです。

まずは手元にmemo.txtを作って、書いて、読んで、追記してみてください。手を動かすと、開いて閉じるという流れが体になじみます。

ここまでお読みいただきありがとうございました。

参考情報

次のアクション

記事で学んだ内容を実際に動かしてみよう

Python WebAcademyでは、ブラウザ上でコードを書きながら基礎から実践まで体系的に学べます。

Python WebAcademyの学習画面

あわせて読む

関連記事

ブログ一覧へ

Python学習ロードマップ

まずはこの3講座から

記事で気になったテーマを、順番に手を動かしながら学べます。

ロードマップを見る