コンテキストマネージャ
CoddyのPythonジャーニー「Object Oriented Programming」セクションの一部 — レッスン 41/64。
コンテキストマネージャを使用すると、必要な時にリソースを正確に割り当て、解放することができます。これらは、エラーが発生した場合でも適切なクリーンアップを確実に行います。
以下は、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 文はこれらのメソッドを自動的に呼び出し、適切なセットアップとクリーンアップを保証します。これは、ファイル、データベース接続、および確実なクリーンアップが必要なその他のリソースに対して特に有用です。
チャレンジ
簡単このチャレンジでは、コンテキストブロックの開始から終了までの経過時間を測定するコンテキストマネージャークラスを実装します。
timer.py-Timerクラスの実装が含まれています(このファイルを編集します)driver.py- 包括的なテストケースが含まれています(変更しないでください)
timer.py 内の TODO コメントに従って Timer コンテキストマネージャーを実装してください。このクラスは以下のことを行う必要があります:
- コンテキストに入る時に開始時間を記録する
- 終了する時に終了時間を記録する
- 経過時間を計算して表示する
チートシート
コンテキストマネージャは、必要な時に正確にリソースを割り当てて解放し、エラーが発生した場合でも適切なクリーンアップを保証します。
自動的なリソース管理には 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")__exit__ メソッドは3つのパラメータを受け取ります:
exc_type: 例外の型(または None)exc_val: 例外の値(または None)exc_tb: 例外のトレースバック(または None)
コンテキストマネージャで例外を処理する:
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 # 例外を抑制しない自分で試してみよう
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秒間待機させます
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。