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 up과tear 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

참고자료

'C Lang > Python Program Diary' 카테고리의 다른 글

Python requests 모듈 간단 정리  (0) 2019.06.14
파이썬 에러처리하기  (0) 2019.06.14
문자열 format하기  (0) 2019.06.10
쓰레드 (Thread)란  (0) 2019.06.07
Process와 Thread의 차이  (0) 2019.06.07

+ Recent posts