개발 꿀팁/PYTHON

Python 컨텍스트 매니저를 이해합니다

Jammie 2022. 12. 2. 10:53
반응형

1. 상황 관리자란 무엇입니까?
우리는 파일을 처리할 때 다음과 같은 코드를 자주 봅니다. 그것은 바로 상황 관리자입니다

with open('test.txt', encoding='utf-8') as f:
    print(f.readlines())

현재 디렉터리에 있는 test.txt 파일을 열고 그 안에 있는 내용을 인쇄하는 것을 의미하며, 아래 코드와 같은 효과를 냅니다

f = open('test.txt', encoding='utf-8')
print(f.readlines())
f.close()

두 가지 쓰기를 비교하면, with를 사용하여 f.close(파일 닫기)의 이 작업을 자동으로 수행함으로써 코드를 조금 적게 쓸 수 있음을 알 수 있습니다.

그럼 이런 상황별 관리자가 어떻게 구현되었는지, 아래에 설명해 드리겠습니다

기사 목록입니다.
1. 상황 관리자란 무엇입니까?
2. 컨텍스트 매니저를 구현하는 방법
1. 클래스로 구현합니다
2. contextlib을 통해 구현합니다
2. 컨텍스트 매니저를 구현하는 방법
1. 클래스로 구현합니다
위의 open의 컨텍스트 매니저 기능을 구현하려면 아래 코드와 같이 클래스를 만들고 _enter_ 및 _exit_ 메서드를 추가하면 됩니다

class DiyOpen(object):

    def __init__(self, filename, **kwargs):
        self.f = open(filename, **kwargs)

    def __enter__(self):
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('파일을 닫습니다')
        self.f.close()


with DiyOpen('test.txt', encoding='utf-8') as f:
    print(f.readlines())

결과를 출력합니다

['첫 번째 줄\n', '두 번째 줄\n', '세 번째 줄']
파일을 닫습니다

파일 내용을 출력한 후 자동으로 파일 닫기 작업이 실행된 것을 볼 수 있습니다.

그럼 _enter_와 __exit_의 의미는 무엇이고, __exit__뒤의 exc_type, exc_val, exc_tb는 또 무슨 뜻일까요?

1)_enter_

__enter__는 상대적으로 이해가 잘 되며, with 문이 나타나면 트리거되고, 반환 값이 있을 때 반환 값이 as 선언의 변수, 즉 우리 위의 asf의 f에 할당됩니다.

2)_exit_

__exit__는 with 실행이 완료된 후 자동으로 실행되며, 그의 뒤에 있는 파라미터의 의미는 다음과 같습니다.

exc_type: 예외 유형입니다.
exc_val: 이상 원인입니다
exc_tb: 스택 추적 정보입니다.
with에서 실행된 코드가 오류를 보고할 때, with에 포함된 코드를 계속 실행하지 않는 것 외에 오류 정보를 아래의 코드와 같은 위의 세 가지 파라미터에 넣습니다

class DiyOpen(object):

    def __init__(self, filename, **kwargs):
        self.f = open(filename, **kwargs)

    def __enter__(self):
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        self.f.close()


with DiyOpen('test.txt', encoding='utf-8') as f:
    print(f.no())

결과를 출력합니다

<class 'AttributeError'>
'_io.TextIOWrapper' object has no attribute 'no'
<traceback object at 0x000002A34B834900>

주의해야 할 점은 다음과 같습니다.

우리는 수동으로 __exit_의 반환 값을 True로 지정하여 오류가 발생하지 않도록 할 수 있습니다.
이상 정보가 없을 경우 위의 세 파라미터 값은 모두 None입니다.
2. contextlib을 통해 구현합니다
Python은 컨텍스트 관리자를 구현하기 위해 contextlib 모듈이 내장되어 있으며 제너레이터 yield를 통해 구현되며 이 모듈은 클래스 및 _enter_와 __exit_를 만들 필요가 없습니다.

contextlib을 통해 open 기능을 구현하는 코드는 다음과 같습니다

from contextlib import contextmanager

@contextmanager
def diy_open(filename, **kwargs):
    f = open(filename, **kwargs)  # __init__
    try:
        yield f  # __enter__
    finally:  # __exit__
        f.close()

with diy_open('test.txt', encoding='utf-8') as f:
    print(f.readlines())

 

반응형