withクリーンアップが必要なリソースの管理には、Pythonのステートメントを使用することをお勧めします。明示的なclose()ステートメントを使用する場合の問題はfinally、例外が発生したときにリソースリークを防ぐために、呼び出しをまったく忘れたり、ブロックに配置し忘れたりすることを心配する必要があることです。
withステートメントを使用するには、次のメソッドを使用してクラスを作成します。
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
上記の例では、
class Package:
def __init__(self):
self.files = []
def __enter__(self):
return self
# ...
def __exit__(self, exc_type, exc_value, traceback):
for file in self.files:
os.unlink(file)
次に、誰かがあなたのクラスを使用したいと思ったとき、彼らは次のことをします:
with Package() as package_obj:
# use package_obj
変数package_objは、Package型のインスタンスになります(これは、__enter__メソッドによって返される値です)。その__exit__メソッドは、例外が発生したかどうかに関係なく、自動的に呼び出されます。
このアプローチをさらに一歩進めることもできます。上記の例では、with句を使用せずに、コンストラクタを使用してパッケージをインスタンス化することができます。あなたはそれが起こりたくないのです。これを修正するには、__enter__および__exit__メソッドを定義するPackageResourceクラスを作成します。次に、Packageクラスが__enter__メソッド内で厳密に定義され、返されます。このようにして、呼び出し元はwithステートメントを使用せずにPackageクラスをインスタンス化できませんでした。
class PackageResource:
def __enter__(self):
class Package:
...
self.package_obj = Package()
return self.package_obj
def __exit__(self, exc_type, exc_value, traceback):
self.package_obj.cleanup()
これは次のように使用します。
with PackageResource() as package_obj:
# use package_obj