본문 바로가기
Python/Python FAQ

Python 파이썬 객체를 올바르게 정리하는 방법은 무엇인가요?, How do I correctly clean up a Python object?

by 베타코드 2023. 9. 13.
반응형

질문


클래스 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 사용
반응형

댓글