コンテキストマネージャ
CoddyのPythonジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 41/64。
Context managersを使うと、必要なときに正確にリソースを確保し、解放できます。エラーが発生した場合でも、適切なクリーンアップが確実に行われます。
ここでは、with文を使用する最も一般的な例を示します:
with open('example.txt', 'w') as file:
file.write('Hello, world!')
# ファイルはここで自動的に閉じられます例外が発生した場合でも、ブロックの後にファイルは自動的に閉じられます。
__enter__ メソッドと __exit__ メソッドを実装して、独自のコンテキストマネージャーを作成します:
class MyContext:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting the context")
return False # 例外を抑制しないカスタムコンテキストマネージャーを使用します:
with MyContext() as ctx:
print("Inside the context")出力:
Entering the context
Inside the context
Exiting the contextデータベース接続用の、より実用的なコンテキストマネージャーを作成しましょう:
class DatabaseConnection:
def __init__(self, db_name):
self.db_name = db_name
self.connection = None
def __enter__(self):
print(f"Connecting to {self.db_name}")
self.connection = f"Connection to {self.db_name}"
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"Closing connection to {self.db_name}")
self.connection = None
with DatabaseConnection("users_db") as conn:
print(f"Using {conn}")
print("Performing database operations...")コンテキストマネージャーで例外を処理する:
class SafeContext:
def __enter__(self):
print("Setting up resources")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Cleaning up resources")
if exc_type:
print(f"An exception occurred: {exc_val}")
return False # 例外を抑制しない
with SafeContext():
print("Working with resources")
# raise ValueError("Something went wrong") # テストするにはコメントを外す出力:
Connecting to users_db
Using Connection to users_db
Performing database operations...
Closing connection to users_db
Setting up resources
Working with resources
Cleaning up resources__exit__メソッドは3つのパラメーターを受け取ります:
exc_type:例外の型(または None)exc_val:例外の値(または None)exc_tb:例外のトレースバック(または None)
重要なポイント:コンテキストマネージャーは、リソースを管理するために __enter__ メソッドと __exit__ メソッドを使用します。with 文はこれらのメソッドを自動的に呼び出し、適切なセットアップとクリーンアップを確実に行います。これは、ファイル、データベース接続、および確実なクリーンアップが必要なその他のリソースに特に役立ちます。
チャレンジ
簡単このチャレンジでは、context ブロックへの entering と exiting の間の elapsed time を測定する context manager class を実装します。
timer.py-Timerclass の実装を含みます(編集するファイルです)driver.py- 包括的なテストケースを含みます(変更しないでください)
timer.py に、TODO コメントに従って Timer context manager を実装してください。class は次の処理を行う必要があります。
- context に entering したときに start time を Record する
- exiting したときに end time を Record する
- elapsed time を Calculate して表示する
自分で試してみよう
from timer import Timer
import time
# テストケースハンドラー
test_case = input()
if test_case == "basic_test":
# 基本機能のテスト
with Timer():
# 何らかの処理をシミュレート
time.sleep(2) # これによりプログラムが2秒間待機します
elif test_case == "nested_contexts":
# ネストされたコンテキストマネージャのテスト
with Timer():
time.sleep(1)
with Timer():
time.sleep(1)
elif test_case == "exception_handling":
# コンテキスト内の例外処理のテスト
try:
with Timer():
time.sleep(1)
raise ValueError("Test exception")
except ValueError as e:
print(f"Caught exception: {e}")
elif test_case == "zero_sleep":
# 最小限のスリープでのテスト
with Timer():
time.sleep(0.001)
elif test_case == "multiple_timers":
# 連続した複数タイマーのテスト
with Timer():
time.sleep(1)
with Timer():
time.sleep(0.5)
with Timer():
time.sleep(2)
elif test_case == "as_decorator":
# 関数コンテキストでのタイマーのテスト
def timed_function():
with Timer():
time.sleep(2)
timed_function()
else:
# デフォルトテスト - 基本機能
with Timer():
# 何らかの処理をシミュレート
time.sleep(2) # これによりプログラムが2秒間待機します
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Pythonオンラインコンパイラ