Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python에서 객체를 올바르게 정리하는 방법

Python 객체 정리(Cleanup)의 기본 원리

Python에서 전역 변수(globals)의 정리는 해당 변수를 None으로 설정하는 방식으로 수행됩니다. 반면 지역 변수(locals)는 세션이 종료되는 시점에 자동으로 소멸합니다. Python이 내부적으로 호출하는 __del__ 메서드는 전역 변수들을 None으로 설정하는 역할을 담당합니다.

객체 정리 예제 코드

다음 코드는 특정 클래스에 생성된 모든 객체를 정리하는 과정을 보여줍니다.

class Counter:
    Count = 0  # 이 클래스로 생성된 객체의 총 개수

    def __init__(self, name):
        self.name = name
        print(name, 'created')
        Counter.Count += 1

    def __del__(self):
        print(self.name, 'deleted')
        Counter.Count -= 1
        if Counter.Count == 0:
            print('Last Counter object deleted')
        else:
            print(Counter.Count, 'Counter objects remaining')

x = Counter("First")
del x

위 코드에서 마지막의 del 문을 제거하면 예외(exception)가 발생하게 됩니다.

Python 공식 문서의 __del__ 관련 경고

경고: __del__() 메서드는 호출되는 시점과 환경이 불안정할 수 있으므로, 실행 도중 발생하는 예외는 무시되며 대신 sys.stderr에 경고 메시지만 출력됩니다. 또한 모듈이 삭제되는 시점(예: 프로그램 실행이 끝나는 시점)에 __del__()이 호출되는 경우, 해당 메서드가 참조하던 다른 전역 변수들이 이미 삭제된 상태일 수 있습니다. 따라서 __del__() 메서드는 외부 불변성(external invariants)을 유지하는 데 필요한 최소한의 작업만 수행하도록 작성해야 합니다.

예외가 발생하는 이유

명시적인 del 호출 없이 프로그램을 종료하면 __del__은 프로그램 마지막에 호출됩니다. 하지만 그 시점에는 Counter 클래스와 Count 변수가 이미 가비지 컬렉터(GC)에 의해 수거되었을 가능성이 있습니다. 객체가 수거되는 순서는 결정적(deterministic)이지 않기 때문입니다. 즉, 발생하는 예외는 Counter가 이미 메모리에서 해제되었다는 의미이며, __del__ 안에서 복잡하거나 정교한 작업을 처리하는 것은 바람직하지 않습니다.

권장되는 두 가지 해결 방법

이러한 문제를 안전하게 해결하기 위해 다음 두 가지 방법을 사용할 수 있습니다.

  • 명시적인 파이널라이저(finalizer) 메서드 사용 — 파일 객체에서 사용하는 close() 메서드처럼, 리소스 해제가 필요한 시점에 직접 호출하는 정리 메서드를 구현합니다.
  • 약한 참조(weak reference) 사용weakref 모듈을 활용하면 객체의 생명 주기를 방해하지 않으면서도 객체가 소멸되었는지 확인하고 정리 로직을 안전하게 처리할 수 있습니다.