【Python】もうclose()忘れはしない!with文によるスマートなリソース管理術
こんにちは。ゆうせいです。
Pythonでファイルを扱う時、f = open(...)
でファイルを開き、処理が終わったら f.close()
で閉じる、という一連の流れを学びますよね。ですが、もし処理の途中でエラーが発生してしまったらどうなるでしょう? f.close()
が実行されず、ファイルが開いたままになってしまうかもしれません。😱
これは「リソースの解放漏れ」と呼ばれる、プログラムが抱えがちな問題の一つです。
この問題を、より安全かつエレガントに解決してくれるのが、今回ご紹介する with
文です。with
文をマスターすれば、あなたのコードはもっと堅牢で「Pythonらしく」なりますよ!
with
文がない頃の課題 🤔 try...finally
with
文が登場する前は、このような問題に対処するために try...finally
という構文が使われていました。finally
ブロックに書かれた処理は、try
ブロックでエラーが起きても起きなくても、必ず実行されることが保証されます。
f = None # fが定義されない場合に備える
try:
f = open("hello.txt", "w", encoding="utf-8")
f.write("こんにちは、世界!")
# f.write(123) # ここでエラーを起こしてみる
finally:
if f is not None:
f.close()
print("ファイルは確実に閉じられました。")
これでも目的は達成できますが、少しコードが長くて、ごちゃごちゃして見えますよね。もっとシンプルに書けないものでしょうか。
with
文による革命 ✨
そこで登場するのが with
文です。先ほどのコードを with
を使って書き換えてみましょう。
with open("hello.txt", "w", encoding="utf-8") as f:
f.write("こんにちは、世界!")
# f.write(123) # ここでエラーが起きても大丈夫!
print("withブロックを抜けました。ファイルは自動的に閉じられています。")
どうでしょうか? try...finally
や close()
の呼び出しが消えて、驚くほどスッキリしましたね!
with
文の魔法は、ブロックの処理が正常に終わっても、エラーで中断しても、ブロックを抜ける時に必ず後片付け処理を自動的に実行してくれる点にあります。
これは、カラオケルームの利用に似ています 🎤。
with 文は、部屋に入るときにマイクやデンモクの電源を入れる「準備」を行い、時間が来て部屋を出るときに、あなたが忘れていてもスタッフが必ず電源を落としてくれる「後片付け」を保証してくれる、そんなスマートなシステムなのです。
with
文の裏側: コンテキストマネージャ
with
文がこれほど便利な働きをできるのは、「コンテキストマネージャ」と呼ばれる仕組みのおかげです。
with
の後ろに書けるオブジェクト(open()
が返すファイルオブジェクトなど)は、すべてコンテキストマネージャのルールに従っています。そのルールとは、以下の2つの特殊メソッドを持っていることです。
__enter__(self)
:with
ブロックに入る時に呼ばれるメソッドです。準備処理をここで行います。このメソッドが返した値がas
の後ろの変数(f
)に代入されます。__exit__(self, exc_type, exc_val, exc_tb)
:with
ブロックから出る時に呼ばれるメソッドです。後片付け処理をここで行います。もしブロック内でエラーが発生した場合、その情報が引数として渡されます。
普段、ファイルなどを扱う際には、これらのメソッドが内部でうまく実装されているため、私たちはその存在を意識することなく、with
文の恩恵だけを受けることができるのです。
Pythonの予約語を調べるとき
キーワード(予約語)について help()
で調べたい場合は、
文字列として渡す必要があります:
help("with")
これで with
文の説明が表示されます。
with
文を使うメリット
with
文のメリットをまとめると、以下のようになります。
- 安全性: 後片付け処理(リソースの解放)が必ず実行されるため、ファイルの閉じ忘れなどを防ぎ、安全なプログラムになります。
- 可読性:
try...finally
に比べてコードがシンプルになり、やりたい処理のブロックが明確になるため、コードが読みやすくなります。 - 再利用性: 自分でコンテキストマネージャを作れば、データベース接続やAPIセッションなど、様々な準備・後片付け処理をカプセル化して、使い回すことができます。(これは少し発展的なお話です!)
これからの学習に向けて
with
文は、ファイルを扱う際の現代的なPythonの「常識」と言っても過言ではありません。今日からでも、ファイルを開く際には必ず with open(...)
を使うように心がけてみてください。
そして、with
文の考え方に慣れてきたら、次は contextlib
という標準ライブラリを調べてみましょう。このライブラリを使えば、__enter__
や __exit__
を持つクラスを自分で書かなくても、もっと簡単に自作のコンテキストマネージャを作れるようになります。
with
文を使いこなして、クリーンで安全なコードを書く楽しさを、ぜひ味わってくださいね!