Python コンテキスト マネージャーが実行できるすべてのことを適切な場所に配置する方法に困惑しています。
私が理解しているように、コンテキストマネージャーを構築する可能性のある要素には次のものがあります。
- A:いつも起こること
- B: C に必要な準備
- C: コンテキストで使用されるオブジェクト X を作成して確立する
- D: コンテキストの開始前に X の確立に成功したことを使用して、いくつかのことを行います
- E: X をコンテキストに戻します ( で使用するため
as
) - F: コンテキストの最後ですべて問題がなければ、X で終了します
- G: コンテキストに入る前に、C と B での失敗の結果に対処する
- H: 状況に応じて失敗の結果に対処する
これらの各要素がコンテキストマネージャー関数のどこにあるのかはおおまかにわかると思いますが、それらをクラスに配置する方法については完全に途方に暮れています。
これらの要素のそれぞれが関数と(特に)クラスの両方に含まれていることを示すコンテキストマネージャー関数とクラスのテンプレートはありますか? ここや他の場所で多くの例を調べましたが、包括的なものはなく、実際のコードを使用しているものも多く、上記の各構成要素に常にマップできるとは限りません。
関数を介して実装された場合のコンテキストマネージャーの動作を基本的に理解していると思います。
from contextlib import contextmanager
@contextmanager
def log_file_open(oec_data, build_description, log_dir):
# A: Something that always happens
try:
# B: Some stuff needed to make a_thing
a_thing = establish_thing_in_a_way_that_might_fail() # C
# D: Some things that happen using a_thing at context start
yield a_thing # E
# F: Wrap up with a_thing when all is well
except:
# G: Deal the consequences of failure in try or...
# H: Deal the consequences of failure in context
finally:
# Could F go here instead?
たとえば、正常に開いて閉じたときに何かを書き込む必要があるが、問題が発生した場合はクリーンアップする必要があるファイルを開くには、次のように記述できます。
from contextlib import contextmanager
@contextmanager
def log_file_open(oec_data, build_description, log_dir):
print('Entering context...')
try:
usable_file_name = get_some_name()
a_thing = open(usable_file_name, mode='w')
a_thing.write('Logging context started.')
yield a_thing
a_thing.write('Logging context ended.')
except:
a_thing.close()
os.remove(a_thing.name)
raise
しかし、これが正しいかどうかはわかりません。また、クラスの使用__enter()__
と__exit()__
クラス内での使用にどのように対応するのか混乱しています。それは(概略的に)ですか:
def __init__(self):
# A: Something that always happens
def __enter__(self):
try:
# B: Some stuff needed to make a_thing
a_thing = establish_thing_in_a_way_that_might_fail() # C
# D: Some things that happen using a_thing at context start
except:
# G: Deal the consequences of failure in try
a_thing = some_appropriate_blank_value
finally:
return a_thing # E
def __exit__(self, type, value, traceback):
if type is None:
# F: Wrap up with a_thing when all is well
return True
else:
# H: Deal the consequences of failure in context
return False