질문
클래스 Package:
def __init__(self):
self.files = []
# ...
def __del__(self):
for file in self.files:
os.unlink(file)
__del__(self)
는 위에서 AttributeError 예외가 발생합니다. 나는 Python은 "전역 변수" (이 맥락에서는 멤버 데이터?)의 존재를 보장하지 않는다는 것을 이해합니다. __del__()
가 호출될 때 예외의 원인이 이것이라면, 객체가 올바르게 해체되도록 어떻게 해야 할까요?
답변
파이썬의 with
문을 사용하여 정리해야 할 리소스를 관리하는 것을 추천합니다. 명시적인 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:
# package_obj 사용
변수 package_obj는 Package 타입의 인스턴스입니다 (__enter__
메서드가 반환하는 값입니다). 예외가 발생하든 발생하지 않든 __exit__
메서드가 자동으로 호출됩니다.
이 접근 방식을 한 단계 더 나아갈 수도 있습니다. 위의 예제에서는 with
절을 사용하지 않고도 Package를 생성자를 사용하여 Package를 인스턴스화할 수 있습니다. 이를 원하지 않습니다. __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:
# package_obj 사용
댓글