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