0Pricing
Python Academy · レッスン

with 文を深く理解する

with の仕組みと、リソースリークを防げる理由を理解します。

「with 文を深く理解する」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。

導入

with文を使うと、例外が発生した場合でも、セットアップと後片付けの処理が必ず実行されます。

withの基本的な使い方

with expr as var:では、exprがコンテキストマネージャーを返す必要があります。varには__enter__が返した値が代入されます。
with open('/tmp/cm_test.txt','w') as f:
    f.write('hello')
print('file closed:', f.closed)

なぜwithが存在するのか

ファイル、ロック、データベース接続などのリソースは解放する必要があります。withを使うと、ブロックの実行中に例外が発生しても後片付けが保証されます。
# Without with:
# f = open('f.txt')
# try: ...
# finally: f.close()
# With with:
# with open('f.txt') as f: ...
print('with is cleaner')

複数のコンテキストマネージャー

with open(a) as f, open(b) as g:のように、1つの文で2つのリソースを開けます。終了時には両方が閉じられます。
import tempfile, os
a = tempfile.mktemp(); b = tempfile.mktemp()
with open(a,'w') as fa, open(b,'w') as fb:
    fa.write('A'); fb.write('B')
os.unlink(a); os.unlink(b)
print('both closed')

withは例外を抑制しない

デフォルトでは、withブロック内の例外は伝播します。__exit__がTrueを返すと、例外を抑制できます。
try:
    with open('/nonexistent.txt') as f:
        pass
except FileNotFoundError as e:
    print('caught:', e)

コンテキストマネージャーとしてのLock

threading.Lock()はコンテキストマネージャーとして機能します。with lock:と記述すると、ロックが必ず解放されます。
import threading
lock = threading.Lock()
with lock:
    print('locked section')
print('lock released')

データベース接続のパターン

データベース接続をコンテキストマネージャーとして使うと、成功時にはコミットし、例外発生時にはロールバックします。重要なパターンです。
# Typical DB pattern:
# with db.transaction() as conn:
#     conn.execute(sql)
# commits on success, rolls back on exception
print('db pattern demo')

ネストしたwith文

with文はネストして問題ありません。内側のコンテキストマネージャーが先に終了し、その後で外側が終了します。
import tempfile
tmp = tempfile.mktemp()
with open(tmp,'w') as outer:
    with open(tmp,'r+') as inner:
        outer.write('x')
import os; os.unlink(tmp)
print('nested exit order')

contextlib.suppress

contextlib.suppress(ExcType)は、withブロック内で指定した例外型を静かに無視します。
from contextlib import suppress
with suppress(FileNotFoundError):
    open('/does/not/exist.txt')
print('no error raised')

contextlib.redirect_stdout

contextlib.redirect_stdout(f)は、print()の出力を一時的にfへリダイレクトします。
from contextlib import redirect_stdout
import io
buf = io.StringIO()
with redirect_stdout(buf):
    print('captured')
print('got:', buf.getvalue())

ExitStack

contextlib.ExitStackは、動的な数のコンテキストマネージャーを管理します。開くファイル数が事前に分からない場合に便利です。
from contextlib import ExitStack
import tempfile, os
with ExitStack() as stack:
    files = [stack.enter_context(open(tempfile.mktemp(),'w')) for _ in range(3)]
    for f in files: f.write('x')
print('all closed')

クイックチェック

contextlib.suppress(FileNotFoundError)は何をしますか?

復習

withは後片付けを保証します。1つのwithで複数の対象を扱えます。contextlib.suppressは特定のエラーを抑制します。ExitStackは動的な数のコンテキストマネージャーを管理します。

学習を続ける

よくできました。次のレッスンが待っています。

よくある質問

「with 文を深く理解する」レッスンは無料ですか?

はい。「with 文を深く理解する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。

「with 文を深く理解する」で何を学びますか?

with の仕組みと、リソースリークを防げる理由を理解します。 ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Python Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「with 文を深く理解する」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPython Academyレッスンでコードを書いて実行できますか?

はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. with 文を深く理解する
  2. __enter__ と __exit__ プロトコル
  3. contextlib: @contextmanager
  4. 実践的なコンテキストマネージャーパターン
← Python Academyに戻る