- 개요
이전까지 클래스의 형태로 Context Manager를 만들어 사용했다
클래스를 만들어 Context Manager를 구현하는 방식은 예외처리를 정교하게 구현할 수 있지만,
만드는 방식이 복잡하여 실질적으로 사용하기는 어렵다
이런 상황에서 함수를 통해 Context Manager를 구현하면 덜 복잡한 방법으로 구현하는 것이 가능하다
함수를 통해 구현하므로 Decorator를 사용하면 훨씬 효율적이다
Decorator는 함수를 직접 수정하지 않고 기능을 추가하고자 할 때 사용할 수 있다
또 Decorator의 경우, annotation을 통해 훨씬 더 쉽게 사용할 수 있다
그러므로 contextlib 모듈을 사용하여 제공되는 Decorator를 이용한 Context Manager 함수를 구현해본다
1) Context Manager 함수의 구현
import contextlib
@contextlib.contextmanager
def my_file_writer(file_name, method):
f = open(file_name, method)
yield f # __enter__
f.close() # __exit__
with my_file_writer('TestFile4.txt', 'w') as f:
f.write('Context Manager Test4.\nContextlib Test4.')
contextlib 모듈을 import하여 제공되는 contextmanager 데코레이터를 사용할 수 있다
@ 연산자를 이용한 annotation 형태로 decorator를 사용하면
함수를 호출할 때, decorator의 기능을 추가하여 사용한다
Context Manager 함수 my_file_writer에서는 파일 이름과 동작 방식을 인자로 받아 동작한다
이때 함수 내부에서 yield 문을 통한 __enter__ 메서드를 구현하고
또 파일 객체를 close하여 __exit__ 메서드를 구현한다

위 Context Manager 함수를 with 함수를 통해 실행하면
수행한 결과에서 파일이 문제없이 작성된 것을 확인할 수 있다
2) Context Manager 함수의 응용
import contextlib
import time
@contextlib.contextmanager
def ExecutionWithTimer(msg):
start = time.monotonic()
try:
# __enter__
yield start
except Exception as e:
print(f'Error Ocurred : {msg} {e}')
raise
else:
# __exit__
print(f'Total time of {msg} : {time.monotonic() - start}')
with ExecutionWithTimer("Hello from decorator") as et:
print(f'Start at {et}')
for i in range(30000000):
pass
이전에 클래스로 만든 순수 실행 시간을 구하는 Context Manager 예제를 함수 형태로 구현하였다
1)의 예제와 동일하게 annotation을 사용하여 decorator를 함수에 적용한다
try 문에서 yield 함수를 통해 __enter__ 메서드를 구현하였고,
except 문을 통해 예외를 처리한다
마지막으로 else 문에서 print 함수를 호출하는 것으로 __exit__ 메서드를 구현하였다

with 함수를 통해 Context Manager 함수를 호출함으로써
msg를 설정하고 3000,0000초 후에 출력하기까지 걸린 시간을 측정할 수 있다
...
with ExecutionWithTimer("Hello from decorator") as et:
print(f'Start at {et}')
for i in range(30000000):
pass
raise Exception("Forced Error")
위와 같이 예외를 발생시키도록 코드를 수정한다면

메세지를 출력 (__exit__)하지 못하고 에러를 출력하는 것을 확인할 수 있다
'Python > 파이썬 오픈소스 배포' 카테고리의 다른 글
| Getter 메서드와 Setter 메서드 (0) | 2025.07.01 |
|---|---|
| 언더스코어(_)의 사용 (0) | 2025.06.30 |
| Context Manager (2) (0) | 2025.06.24 |
| Context Manager (1) (0) | 2025.06.24 |
| 객체의 복사 (0) | 2025.06.23 |