-
Python3 with catchProgramming Language/Python3 2021. 10. 25. 19:01
with
statementpython에서
with
문을 사용하는 것은 파일을 읽을 때, 장점이 있다.with open("./note.txt") as f: text = f.read() # f.close()
with
문이 종료할 때 별도로.close()
를 하지 않아도 종료해주기 때문에 안전하게 파일에 접근할 수 있다.
그렇다면 내 생각엔with
문으로 파일을 읽는 동안 발생하는 에러에 대해서with except
문같은 구문이 있지 않을까 생각했다.
결론
결론부터 말하면, 그러한 문법은 존재하지 않았다.
아래의 답변은with
문을try
로 감싸거나, 파일을 열 때try
로 감싸고 그 후 에러가 없는 경우with
를 쓰는 코드를 보여주고 있다.- try-with
from __future__ import with_statement try: with open( "a.txt" ) as f : print f.readlines() except EnvironmentError: # parent of IOError, OSError *and* WindowsError where available print 'oops'
- try open-else with
try: f = open('foo.txt') except IOError: print('error') else: with f: print f.readlines()
내 결론
난 위의 방법이 아닌 그저
with
문을 안쓰는 쪽을 선택했다.
Deep dive
그런데 아직도 이상하다. 왜 지원해주지 않는걸까?
stackoverflow catching-an-exception-while-using-a-python-with-statement에서 a_guest의 답변에 따르면ContextManager
때문이라고 한다.자세한 내용까지는 다 이해하지 못했지만, 개략적으로 이야기하자면
ContextManager
의 동작방식때문이라고 한다. PEP 343의 예시에 따르면 아래의 코드와with
문이 동일한 형태라고 한다.import sys try: mgr = ContextManager() except ValueError as err: print('__init__ raised:', err) else: try: value = type(mgr).__enter__(mgr) except ValueError as err: print('__enter__ raised:', err) else: exit = type(mgr).__exit__ exc = True try: try: BLOCK except TypeError: pass except: exc = False try: exit_val = exit(mgr, *sys.exc_info()) except ValueError as err: print('__exit__ raised:', err) else: if not exit_val: raise except ValueError as err: print('BLOCK raised:', err) finally: if exc: try: exit(mgr, None, None, None) except ValueError as err: print('__exit__ raised:', err)
코드에서는 아래와 같은 경우에서
raise
가 발생한다. (코드에서는 print로 표시되어 있다.)ContextManager.__init__
ContextManager.__enter__
- the body of the
with
ContextManager.__exit__
with
-except
를 쓸 수 없는 이유는raise
가 여러 곳에서 발생하기 때문이라고 이해했다.
물론except
로 발생하는 모든 예외를 잡을 수 있을 것이다. 하지만 그것은 잘못된 표현법이다.
왜냐하면 외부에서 봤을 때with
문은 한줄이기 때문에 하나의 뎁스?의 코드가 동작하고 반환되는 것 같지만 실제로는 여러 뎁스의 동작이 존재하기 때문에 명시적으로with
-except
문을 사용하게 되면, 사용자는with
에서 발생한 에러에 대해 추상적으로 판단하게 될 것이다.어쨌든
with
문은 굉장히 추상화되어 있는 구문이다.
좋은 표현법이라고 하기 어렵겠다.
References
'Programming Language > Python3' 카테고리의 다른 글
"private" in python (0) 2021.10.25 `pipenv`는 정말 좋다. (0) 2021.10.25 파이썬 내부 클래스에 대해 (0) 2021.10.25 Pytest에 대해 알아보자. (0) 2021.10.25 [번역] Pytest fixture (0) 2021.10.25