【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...finallyclose() の呼び出しが消えて、驚くほどスッキリしましたね!

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 文を使いこなして、クリーンで安全なコードを書く楽しさを、ぜひ味わってくださいね!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。