Python with 구문과 context manager 이해하기

Reading time ~2 minutes

pytest doc의 The writing and reporting of assertions in tests 을 읽어보던 중에 with 구문과 context manager에 대한 내용이 있었는데 개념을 잘 몰라서 정리해봤다. 관련 글인 Understanding Python’s “with” statement을 참고하여 작성했다.


with은 파이썬 2.5에서 도입된 기능으로 context manager에 의해서 실행되는 __enter__()__exit__()을 정의하여, with 구문 body 의 앞부분과 뒷부분에 실행되는 코드를 대신할 수 있다.
with 구문을 이용하면 try/finally을 대신하여 더 간편하고 쉽게 사용할 수 있다.

아래의 예제 코드를 보자.

set things up
try:
    do something
finally:
    tear things down

set things up에는 file을 열거나 외부 리소스와 같은 것을 얻는 처리가 해당되고, tear things down에는 file을 닫거나 리소스를 제거, 해제 하는 처리가 해당된다. 이와 같은 try-finally 구조는 코드가 제대로 동작하지 않고 끝나더라도 tear things down은 무조건 실행되는 것을 보장한다.

이런 코드는 많이 사용되는 것으로, 아래와 같이 set things uptear things down 부분을 __enter__()__exit__()을 정의하여 사용한다면 재사용성이 높아지고 편리할 것이다.

class controlled_execution:
    def __enter__(self):
        set things up
        return thing
    def __exit__(self, type, value, traceback):
        tear things down

with controlled_execution() as thing:
     some code using thing

with 구문이 실행되면, context manager에 의해서 __enter__이 실행되고 여기서 반환하는 값이 as의 thing로 지정된다. 그 후에 some code using thing에 해당하는 body code를 실행하고, 코드에 무슨 일이 있다 하더라도 마지막에 __exit__은 호출이 보장된다.

python의 file 객체는 __enter____exit__ 함수가 구현되어있다. 전자는 file object 객체 자신을 리턴하고, 후자는 file을 close 한다.

>>> f = open("x.txt")
>>> f
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.__enter__()
<open file 'x.txt', mode 'r' at 0x00AE82F0>
>>> f.read(1)
'X'
>>> f.__exit__(None, None, None)
>>> f.read(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file

따라서 file을 열고, 사용한 후에 닫는 것을 보장하도록 하는 것을 아래처럼 매우 간단하게 사용할 수 있다.

with open("x.txt") as f:
    data = f.read()
    do something


참고자료

https://docs.python.org/3/reference/datamodel.html#context-managers
http://effbot.org/zone/python-with-statement.htm

pytest doc 번역 - The writing and reporting of assertions in tests

지난 포스트(pytest doc 번역 - Installation and Getting Started)에 이어서 pytest Documentation의 The writing and reporting of assertions in tests 라는...… Continue reading