0Pricing
Python Academy · レッスン

実践的なコンテキストマネージャーパターン

ファイル、ロック、タイマー、DB 接続にコンテキストマネージャーを適用します。

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

概要

コンテキストマネージャーは、ファイル、データベース、ロック、タイマーなど、現実のさまざまなリソース管理の問題をエレガントに解決します。

ファイル処理パイプライン

入力ファイルと出力ファイルを同時に開き、1行ずつ処理して、両方を自動的に閉じます。
import io
src = io.StringIO('line1\nline2\nline3')
dst = io.StringIO()
with src, dst:
    for line in src:
        dst.write(line.upper())
print(dst.getvalue())

データベーストランザクション

DB操作をCMで囲み、成功時にはコミットし、例外発生時にはロールバックし、常に閉じるようにします。
from contextlib import contextmanager
@contextmanager
def db_transaction(conn):
    try:
        yield conn
        print('COMMIT')
    except Exception as e:
        print(f'ROLLBACK: {e}')
        raise
    finally:
        print('CLOSE')
with db_transaction({'execute': lambda q: print(f'SQL: {q}')}) as db:
    db['execute']('INSERT ...')

スレッドロック

with lock:はロックを取得し、本文を実行して、終了時にロックを解放します。手動でacquire/releaseを呼び出す必要はありません。
import threading
lock = threading.Lock()
shared = []
def add(x):
    with lock:
        shared.append(x)
add(1); add(2)
print(shared)

カレントディレクトリの変更

os.chdir()は作業ディレクトリをグローバルに変更します。CMを使うと、変更前のディレクトリを保存して復元できます。
from contextlib import contextmanager
import os
@contextmanager
def chdir(path):
    old = os.getcwd()
    os.chdir(path)
    try: yield
    finally: os.chdir(old)
original = os.getcwd()
with chdir('/tmp'):
    print('in tmp:', os.getcwd())
print('back:', os.getcwd())

一時ファイル

tempfile.NamedTemporaryFile as a CMを使うと、一時ファイルを自動的に作成して削除できます。
import tempfile
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=True) as f:
    f.write('temp data')
    print('temp file:', f.name)
print('deleted')

環境変数の一時変更

テストやサブプロセス用に環境変数を一時的に設定し、その後で元に戻します。
from contextlib import contextmanager
import os
@contextmanager
def env(**kwargs):
    old = {k: os.environ.get(k) for k in kwargs}
    os.environ.update({k:str(v) for k,v in kwargs.items()})
    try: yield
    finally:
        for k,v in old.items():
            if v is None: os.environ.pop(k,None)
            else: os.environ[k]=v
with env(DEBUG='1', LOG_LEVEL='DEBUG'):
    print(os.environ['DEBUG'])

プロファイリングブロック

ブロックをcProfileで囲み、CM内でその処理のパフォーマンスを測定します。
from contextlib import contextmanager
import cProfile
@contextmanager
def profile():
    pr = cProfile.Profile()
    pr.enable()
    yield pr
    pr.disable()
with profile() as pr:
    sum(range(1000000))
print('profiled')

ネットワークソケット

ソケットはCMプロトコルを実装しています。with socket.socket() as s:と書くと、終了時にソケットが閉じられます。
import socket
try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.settimeout(0.1)
        print('socket ready')
except Exception as e:
    print(f'socket: {e}')

警告の捕捉

warnings.catch_warnings()はブロック内で発生した警告を捕捉します。テストで便利です。
import warnings
with warnings.catch_warnings(record=True) as w:
    warnings.simplefilter('always')
    warnings.warn('test warning')
print(len(w), w[0].category.__name__)

パターンの組み合わせ

現実のCMでは、トランザクション、ロギング、時間計測など、複数のパターンを1つの再利用可能なコンポーネントに組み合わせることがよくあります。
from contextlib import contextmanager
import time
@contextmanager
def timed_operation(name):
    print(f'[{name}] start')
    t0 = time.perf_counter()
    try:
        yield
        print(f'[{name}] done in {time.perf_counter()-t0:.4f}s')
    except Exception as e:
        print(f'[{name}] failed: {e}')
        raise
with timed_operation('loop'):
    sum(range(100000))

クイックチェック

安全な並行アクセスのためにコンテキストマネージャープロトコルを実装しているスレッド処理プリミティブはどれですか?

まとめ

コンテキストマネージャーのパターンには、ファイル処理パイプライン、DBトランザクション、ロック、ディレクトリ変更、一時ファイル、環境変数の一時変更、プロファイリングがあります。動的なリソーススタックにはExitStackを使います。

続けましょう

素晴らしい成果です!次のレッスンが待っています。

よくある質問

「実践的なコンテキストマネージャーパターン」レッスンは無料ですか?

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

「実践的なコンテキストマネージャーパターン」で何を学びますか?

ファイル、ロック、タイマー、DB 接続にコンテキストマネージャーを適用します。 ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「実践的なコンテキストマネージャーパターン」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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