[ Python ] 파이썬 객체에서 with 사용 - 슬기로운 파이썬 트릭 책 中

2019. 9. 29. 17:54분석 Python/책 구현 리뷰

728x90

슬기로운 파이썬 트릭이라는 책에서 나오는 객체엇 with 사용 부분

일반적으로 먼가 쓰고 닫을 때 다음과 같이 진행을 한다.

f = open("hello.txt", "w")
f.write("text")
f.close()

하지만 이런식으로 진행하다 보면, f.write 도중에 에러가 발생하면 파일이 닫히는 것을 보장하지 않아서 리소스 누수가 발생할 수 있다. 그래서 이것을 다음과 같이 해결할 수 있다.

f = open("hello.txt", "w")
try :
    f.write("text")
finally :
    f.close()

하지만 이러면 코드가 굉장히 지저분해보일 수 있다. 

그래서 책에서는 with를 사용해서 리소스를 적절하게 확보하고 반환하는 것을 하는 게 좋다고 한다.

책에서는 contextmanager를 구현하면, 자신의 클래스나 함수에도 동일 기능을 제공할 수 있다고 한다. 

그러면 contextmanager란?

with 문을 지원하기 위해 객체가 따라야 하는 간단한 프로토콜(인터페이스)라고 책에서는 말한다. 

그래서 기본 contextmanager로 사용하려는 객체에는 __enter__ , __exit__ 가 필요하다고 한다. 

그러면 파이선이 리소스 관리 주기의 적절한 시기에 이 두 메소드를 호출한다고 한다.

class ManagedFile :
    def __init__(self , name) :
        self.name = name
    
    def __enter__(self) :
        self.file = open(self.name, "w")
        return self.file
    
    def __exit__(self , exc_type , exc_val , exc_tb) :
        if self.file :
            self.file.close()
            
with ManagedFile("hello.txt") as f :
    f.write("test")
    f.write("test2")

그래서 다음과 같이 사용할 수 있다고 한다.

이렇게 with문의 context가 들어가니 __enter__ , 그때 리소스를 확보한 다음에 __exit__를 호출하고 호출하여 리소스를 반환한다고 한다. 

이렇게 클래스 기반 context manager 만 있는게 아니라 contextlib도 있다고 한다. 이 모듈은 기본 콘텍스트 매니저 프로토콜 위에 구축된 몇 가지 추상화를 제공한다(?) 여기서는 그래서 contexlib.contextmanager라는 decorator를 사용한다.

from contextlib import contextmanager
@contextmanager
def managed_file(name) :
    try :
        f = open(name , "w")
        yield f
    finally :
        f.close()

with managed_file("hello2.txt") as f :
    f.write("hi")
    f.write("hi2")
        

이 둘중에 정답은 없고 가독성이 좋은 것을 선택하면 된다고 한다. 

난 @contextmanger 같이 아직 decorator의 개념을 이해도가 적어서 그런지 위의 것이 더 맘이 편하다.

 

728x90