【Python】with文を理解して使う

こんにちは!

今回は、Pythonのwith文についてです。

皆さんは、with文使ってますか?多くの場合with文を使わなくてもプログラムは動きますが、with文を使うことで得られるメリットもあります。

今回は、with文の使い方と、そのメリットについて紹介していきます。

with文とは

with文は、一定期間だけオブジェクトを使用したりする場合に使います

ファイルやデータベースにアクセスする際がその例です。

以下は、sample.txtを読み込む例です。

with open("sample.txt") as sample:
    print(sample.read())

with文の特徴として、with文のブロックが終了した時点でファイルオブジェクトがクローズされます

本来なら以下のようにtry~catchで記述しないといけないところを、簡略に記述することができます。

sample = open("sample.txt")
try:
    text = sample.read()
finally:
    sample.close()

メリット

with文のメリットは簡略な記述だけではありません。

ファイルやデータベースにアクセスした際、最後にクローズしなければなりませんが、with文ではそれを記述する必要がありません

なので、記述漏れを防ぐことができ、より安全にコーディングを行うことができます。

構文

基本的な構文は上記の通りです。with文では、複数のオブジェクトをまとめて操作することもできます。

以下に方法をいくつか紹介しますが、あくまで動くけど、、、という構文もあります。自分なりにわかりやすい方法を選んで使ってください。

*コードについては以下サイトから

https://www.python.jp/pages/with-statement-3.9.html

方法①

with open("file1") as file1:
    with open("file2") as file2:
        with open("file3") as file3:
            print(file1.read(), file2.read(), file3.read())

with文をネストにすることで複数のオブジェクトを扱えます。

が、見づらく実用性には欠けます。オブジェクトが増えれば増えるほど階層が深くなるのも気にいらない点です。

方法②

with open("file1") as file1, open("file2") as file2, open("file3") as file3:
    print(file1.read(), file2.read(), file3.read())

方法①よりはかなりマシです。

しかし、先頭行がオブジェクトの数だけ長くなってしまう点が気に入らない方もいるのでは?と思います。

そこでやりたくなるのが先頭行の改行ですが、そのまま改行するとエラーになってしまいます。改行するときは、行末に \ を入れます。

with open("file1") as file1, \
     open("file2") as file2, \
     open("file3") as file3:

    print(file1.read(), file2.read(), file3.read())

結局見にくいような気もしますが^^;

方法③

Python3.3以降を使っているのであれば、contextlib.ExitStackを使うことで以下のように記述することができます。

from contextlib import ExitStack 

with ExitStack() as stack:
    file1 = stack.enter_context(open("file1"))
    file2 = stack.enter_context(open("file2"))
    file3 = stack.enter_context(open("file3"))

  print(file1.read(), file2.read(), file3.read())

これまでよりも相当すっきりしたように感じます。

方法④

Python3.9以降であれば、以下のような書き方もできるようになりました。

with (open("file1") as file1, 
      open("file2") as file2,
      open("file3") as file3):

    print(file1.read(), file2.read(), file3.read())

方法②と似ているような気もしますが、この方法ではオブジェクトをタプルのように指定します。

\ も不要ですし、よりシンプルな書き方なのではないかと思います。

まとめ

with文についてまとめてみました。

使わなくてもプログラムは書けますが、

  • シンプルに記述する
  • 安全に記述する

といった観点からも、with文を使えるところは使った方がいいのではと思います。

特に、ファイルの読み書きが多いようなプログラムでは、クローズの記述が抜けたりしがちなので、それを防ぐ意味でもwith文を使ってみてください。

ではでは👋