pythonのコンテキストマネージャ
2677 ワード
コンテキストマネージャとは?
コードの環境はコンテキストであり,コンテキストマネージャプロトコルを実現したクラスの生成例がコンテキストマネージャオブジェクトである.クラス内の名前enterメソッドとexitメソッドの就き時にコンテキストマネージャプロトコルが実装されます.すなわち、この2つのメソッドが定義されている限り、このクラスのインスタンスはコンテキストマネージャオブジェクトです.
データベースへの適用
コンテキストマネージャオブジェクトが適用されない場合、私たちは一般的に接続データベース、sql操作、データの読み取り、接続の切断という順序で符号化を行いますが、接続データベースと接続の切断という2つの操作はすべての操作でしなければならないことなので、sqlが大量にある場合、このような論理的なコードによって大量の冗長コードが発生します.まず、最も原始的な書き方を見てみましょう.
上記のコードでは、データベースに接続されているかどうかを示すconnectedプロパティを定義するデータベースクラスDatabaseが作成されています.接続メソッドは、データベースへの接続操作を表します.closeメソッドは、データベース接続を閉じることを表します.queryメソッドはクエリー操作を表します.これは最も考えやすく、最も基礎的な操作論理でもある.
ジェネレータもこの問題を解決できます
ジェネレータは本質的に、あなたが書いた関数にインタフェースをセットしたような方法です.簡単な例を見てみましょう
withこの問題をより優雅に解決できる
Databaseというクラスにはenterとexitメソッドが含まれていることが明らかになった.これにより、Database()はコンテキストマネージャプロトコルを実装したオブジェクトを生成し、with文を使用することができます.with文は接続と切断を自動的に処理します.
with文はどうして自動的に処理されますか?
もちろんコードを使って制御する必要があります.まずwith Database()as db:このコードのdbはenterメソッドの戻り値です.また、この文を実行するときにコードがenterメソッドを先に実行し、データベースに接続する操作を行います.そしてprint(「handle...」を実行し、db.query()というコードは、クエリーsqlの処理を表す.print文(つまりクエリー文)が実行されると、exitメソッドがコールバックされ、ここにデータベース接続を閉じるコードが書き込まれます.これにより、無制限に接続と切断されたコードを書く必要はありません.完璧に解決する.
このexitメソッドは、with文の関数体に異常が発生した場合にeixtメソッドも呼び出されるため、データベースの接続が切断されるため、安全です.
コードの環境はコンテキストであり,コンテキストマネージャプロトコルを実現したクラスの生成例がコンテキストマネージャオブジェクトである.クラス内の名前enterメソッドとexitメソッドの就き時にコンテキストマネージャプロトコルが実装されます.すなわち、この2つのメソッドが定義されている限り、このクラスのインスタンスはコンテキストマネージャオブジェクトです.
データベースへの適用
コンテキストマネージャオブジェクトが適用されない場合、私たちは一般的に接続データベース、sql操作、データの読み取り、接続の切断という順序で符号化を行いますが、接続データベースと接続の切断という2つの操作はすべての操作でしなければならないことなので、sqlが大量にある場合、このような論理的なコードによって大量の冗長コードが発生します.まず、最も原始的な書き方を見てみましょう.
class Database():
def __init__(self):
self.connected = False
def connect(self):
self.connected = True
def close(self):
self.connected = False
def query(self):
if self.connected:
return "query data"
else:
raise ValueError("DB not connected.")
def handle_query():
db = Database()
db.connect()
print("handling......", db.query())
db.close()
上記のコードでは、データベースに接続されているかどうかを示すconnectedプロパティを定義するデータベースクラスDatabaseが作成されています.接続メソッドは、データベースへの接続操作を表します.closeメソッドは、データベース接続を閉じることを表します.queryメソッドはクエリー操作を表します.これは最も考えやすく、最も基礎的な操作論理でもある.
ジェネレータもこの問題を解決できます
ジェネレータは本質的に、あなたが書いた関数にインタフェースをセットしたような方法です.簡単な例を見てみましょう
def dbconn(fn):
def wrapper(*args, **kwargs):
db = Database()
db.connect()
ret = fn(db, *args, **kwargs)
db.close()
return ret
return wrapper
@dbconn
def handle_query(db=None):
print("handle---", db.query())
withこの問題をより優雅に解決できる
class Database():
def __init__(self):
self.connected = False
def connect(self):
self.connected = True
def close(self):
self.connected = False
def query(self):
if self.connected:
return "query data"
else:
raise ValueError("DB not connected.")
def __enter__(self):
self.connect()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
# with
def handle_query():
with Database() as db:
print("handle...", db.query())
# handle_query()
handle_query()
Databaseというクラスにはenterとexitメソッドが含まれていることが明らかになった.これにより、Database()はコンテキストマネージャプロトコルを実装したオブジェクトを生成し、with文を使用することができます.with文は接続と切断を自動的に処理します.
with文はどうして自動的に処理されますか?
もちろんコードを使って制御する必要があります.まずwith Database()as db:このコードのdbはenterメソッドの戻り値です.また、この文を実行するときにコードがenterメソッドを先に実行し、データベースに接続する操作を行います.そしてprint(「handle...」を実行し、db.query()というコードは、クエリーsqlの処理を表す.print文(つまりクエリー文)が実行されると、exitメソッドがコールバックされ、ここにデータベース接続を閉じるコードが書き込まれます.これにより、無制限に接続と切断されたコードを書く必要はありません.完璧に解決する.
このexitメソッドは、with文の関数体に異常が発生した場合にeixtメソッドも呼び出されるため、データベースの接続が切断されるため、安全です.