1. Exception 발생 시 기본 동작
Python에서 무엇인가가 잘못된 경우, python interpreter는 exception을 발생시킴.
- Exception : 동작을 중단시키는 에러를 가르킴.
- Exception handling : Exception 처리라고도 불리며, 발생한 exception을 처리하여 프로그램이 비정상적 중단(crash)되지않도록 처리하는 것을 가르킴.
Python에서 exception이 발생할 경우, 프로그램은 더 이상 수행하지 않고 종료된다.
(해당 문제를 그냥 안고 가는 것보다 사용자에게 문제가 발생했다는 것을 알리고 종료하는 게 일반적으로 더 나은 대처임)
참고로 이와 같은 종료를 crash 발생이라고도 한다.
Python에서는 Excpetion 이라는 type으로 예외를 추상화하고 있음.
추상화(abstraction)에 대한 개념이 약하다면 다음 접은 글을 참조
다음의 hierarchy (계층)를 참고.
>>> ValueError.mro()
[<class 'ValueError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>]
Python의 Exception Hierarchy 와 간략한 설명은 다음 접은 글의 URL을 참고할 것.
2. try and except 를 통한 Exception 처리.
crash 없이 안정적으로 동작하는 프로그램을 만들려면,
발생가능한 exception들을 예측하고
발생가능한 부분에 이들 excpetion을 처리(handle)하는 code들을 작성해야만 한다.
이 같은 처리는 try와 except를 이용한다.
try:
exception이 발생가능한 부분
.
.
.
except 처리할_Exception0 as 별칭:
별칭을 통한 Exception 객체에 대한 접근
excpetion 발생시 실행되는 code 들.
.
.
.
except 처리할_Exception1 as 별칭:
또 다른 Type의 Exception에 대한 처리 부분.
앞서 except에서 처리가 되지 않은 경우에 처리가 됨(elif와 비슷)
.
.
.
finally:
exception 발생에 상관없이 수행되는 처리 부분.
.
.
.
위의 pseudo code는 Exception
을 처리하는 방법을 간략하게 나타내고 있음 (별칭=alias).
즉, 간단하게 except
code block들은 처리할 Exception 별로 만들어주면 된다.
- 참고로
finally
블럭은 생략가능함. 꼭 마지막에 처리해야 하는 코드들이 있는 경우 사용한다. except
블록에서 처리하지 않는 Exception들은 Python interpreter에게 전달되고 프로그램 종료로 이어진다.raise
를 이용하여 except에서 처리하고 해당 exception을 다시 interpreter에게 넘길 수도 있음. (이 경우 프로그램은 exception으로 종료됨)raise ValueError('invalid argument')
와 같이 특정한 exception을 발생시키도록 처리할 수도 있음.
3. Example 1
다음 예는
0으로 나누어주는 ZeroDivisionError
와
잘못된 입력으로 인한 ValueError
를
handling하도록 만든 예제임.
def divide( a, b ):
return a/b
def main():
try:
a_str = input('numerator=?')
a = int(a_str)
b_str = input('denominator=?')
b = int(b_str)
r = divide(a,b)
print(f'result = {r}')
except ValueError as ve:
print(ve) # ve라는 alias를 통해 발생한 Exceptoin 객체에 접근 가능.
print(f'Check your inputs')
raise ValueError("잘못된 input value입니다.")
except ZeroDivisionError as ze:
print(ze) # ze라는 alias를 통해 발생한 Exceptoin 객체에 접근 가능.
print(f'denominator can not be zero!')
finally:
print('This python scirpt is finished.')
main()
- int로 casting이 안되는 입력을 할 경우, ValueError가 발생하고,
해당 Exception은 raise를 통해 interpreter에게 던져지므로 프로그램이 비정상종료됨. - 0이 입력된 경우, raise가 없이 exception에서 처리되어 프로그램은 정상종료됨.
- 비정상종료도 finally 블럭이 수행되고 나서임.
4. 모든 Exception 한 번에 처리
만일 모든 Exception을 한방에 처리하려면 except:
형태로 시작하는 exception처리 블록을 만들면 된다.
except:
모든 예외 처리.
- 모든 exception을 단 하나의 블럭으로 처리하는 이 같은 처리는 권하진 않는다. ==;;
- 해당
except
블럭은finally
와 다른 명시적으로 처리할 Exception을 지정한except
블럭 사이에 놓임. - 해당
except
블럭 위에 명시적으로 처리할 exception들에 대한 except블록을 놓여 있을 경우, 해당 exceptoin을 제외한 exception들을 처리함.
참고로 모든 처리할 수 있는 예외들은
Exception의 subclass이므로except Excetion:
또는except Excetion as all_e:
등으로 모든 예외를 처리할 수 있음.
다음 예를 참고.
def divide( a, b ):
return a/b
def main():
try:
a_str = input('numerator=?')
a = int(a_str)
b_str = input('denominator=?')
b = int(b_str)
r = divide(a,b)
print(f'result = {r}')
except ValueError as ve:
print(ve) # ve라는 alias를 통해 발생한 Exceptoin 객체에 접근 가능.
print(f'Check your inputs')
except: # except Exception as all_e:
print(f'Exception Occured!')
raise
finally:
print('This python scirpt is finished.')
main()
- except 블럭에서 raise 가 있기 때문에 interpreter에게 발생한 exception이 전달됨.
- 즉, 이 경우 비정상 종료됨. 정상종료시키려면 except 블럭에서 raise 문을 제거해야 함.
- 비정상종료도 finally 블럭이 수행되고 나서임.
비정상 종료시 PVM이 OS에게 반환하는 종료상태코드 를 확인해볼 것.
5. else 블럭.
except 블럭과 finally 블럭 사이에 위치하며,
try 블럭에서 exception이 발생하지 않은 경우에만 수행되는 블럭임.
def divide( a, b ):
return a/b
def main():
try:
a_str = input('numerator=?')
a = int(a_str)
b_str = input('denominator=?')
b = int(b_str)
r = divide(a,b)
print(f'result = {r}')
except ValueError as ve:
print(ve) # ve라는 alias를 통해 발생한 Exceptoin 객체에 접근 가능.
print(f'Check your inputs')
except:
print(f'Exception Occurred!')
else:
print('There is no error!')
finally:
print('This python script is finished.')
main()
- exception이 발생하지 않은 경우
else
블럭과finally
블럭이 수행됨. finally
는 항상 수행됨.
참고자료
https://gist.github.com/dsaint31x/94e6ec9a825ce31cb215932cbc56a3fa#file-py_exception_handling-ipynb
https://ds31x.tistory.com/page/Python-Python-%EC%A0%95%EB%A6%AC
'Programming' 카테고리의 다른 글
[Python] Module Search Path and sys.path (0) | 2023.06.18 |
---|---|
[Python] importlib.reload : module 재적재 (0) | 2023.06.18 |
[Python] Strong Typing이란? with Object (1) | 2023.06.13 |
[Python] Variable (and Object) (0) | 2023.06.13 |
[Python] Arithmetic in Python and Augmented Assigment (0) | 2023.06.12 |