Python - 예외처리 try , except, raise
:: python tutorial :: Errors and Exceptions
프로그램을 만들다 보면 수없이 많은 오류를 만나게 된다. 물론 오류가 발생하는 이유는 프로그램이 잘못 동작되는 것을 막기 위한 파이썬의 배려이다. 하지만 때때로 이러한 오류를 무시하고 싶을 때도 있고 별도로 처리하고 싶을 때도 있다. 이에 파이썬은 try, except를 이용해서 오류를 처리할 수 있게 해준다.
오류가 발생하는 경우는?
파이썬은 매우 친절하게도 오류(Error) 타입을 분류해서 사용자에게 알려주고 있다.
그럼에도 불구하고 이런 친절함을 이해하지 못하고, 활용하지 못한다면 무슨 소용이 있을까 ?
이번엔 프로그램에서 자주 발생하는 오류의 예시를 살펴보고 오류를 처리하는 방법을 배워 보도록 한다.
IndexError
In [1]: list = []
In [2]: list[0]
-----------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-2-3f96b4c58ba4> in <module>()
----> 1 list[0]
IndexError: list index out of range
- 이 예제를 보면 빈 리스트에서
list[0]
의 값을 가져오려고 하면IndexError
(색인오류)가 발생한다.
ValueError
In [3]: text = 'abc'
In [4]: number = int(text)
-----------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-cad86af3a9b3> in <module>()
----> 1 number = int(text)
ValueError: invalid literal for int() with base 10: 'abc'
-
number
라는 변수에text 변수 'abc'
를int
로 바꾸려고 한다. -
'abc'
는 숫자로 바꿀 수 없기 때문에ValueError
가 발생한다.
try / except
다음은 오류 처리를 위한 try, except문의 기본 구조이다.
에러가 발생할 것 같은 코드를 try:
아래 블럭에 놓고 except
에 발생할 수 있는 에러의 이름 NameError
을 적어두면, 에러가 발생할 경우 별도로 처리해 줄 수 있다.
에러 처리를 해주지 않는다면 에러가 발생해 프로그램이 멈추는 불상사가 일어날 것이다.
text = "100%"
try:
number = int(text)
except ValueError:
print('{}는 숫자가 아닙니다.'.format(text))
---------------------------------------------------------------
> 100%는 숫자가 아닙니다.
if / else
경우에 따라서 if / else로 바꿔 사용할 수 있다. 코드가 더 간결한 것을 선택해 사용한다.
# try-except 문
def safe_pop_print(list, index):
try:
print(list.pop(index))
except IndexError:
print('{} index의 값을 가져올 수 없습니다.'.format(index))
safe_pop_print([1,2,3], 5) #
------------------------------------------------------------------
> 5 index의 값을 가져올 수 없습니다.
# if 문
def safe_pop_print(list, index):
if index < len(list):
print(list.pop(index))
else:
print('{} index의 값을 가져올 수 없습니다.'.format(index))
safe_pop_print([1,2,3], 5)
------------------------------------------------------------------
> 5 index의 값을 가져올 수 없습니다.
try /except 가 아니면 예외처리가 안되는 경우
try:
import my_module
except ImportError:
print("모듈이 없습니다.")
예외 이름과 상관 없이 에러처리
try:
list=[]
print(list[0]) # 빈리스트의 값을 불러오는 경우 Error가 발생
text = 'abc'
number = int(text) # 문자열을 정수로 불러오면 Error가 발생
except:
print('에러가 발생했습니다.')
except.py
에러가 발생했습니다.
예외 이름을 모르는 경우 처리 방법
try:
# 에러가 발생할 가능성이 있는 코드
except Exception as ex: # 에러 종류
print('에러가 발생 했습니다', ex) # ex는 발생한 에러의 이름을 받아오는 변수
try:
# list=[]
# print(list[0])
text = 'abc'
number = int(text)
except Exception as ex:
print('에러가 발생했습니다.', ex)
except.py
에러가 발생했습니다. invalid literal for int() with base 10: 'abc'
try:
list=[]
print(list[0])
# text = 'abc'
# number = int(text)
except Exception as ex:
print('에러가 발생했습니다.', ex)
python except.py
에러가 발생했습니다. list index out of range
raise 예외 발생
raise
를 통해 에러를 직접 발생시킨다.
def rsp(mine, yours): # 나와 , 상대방
allowed = ['가위','바위', '보']
if mine not in allowed: # mine 에 '가위', '바위', '보' 중에 있는지 검사
raise ValueError # 없으면 ValueError 발생
if yours not in allowed: # yours 에 '가위', '바위', '보' 중에 있는지 검사
raise ValueError # 없으면 ValueError 발생
# 가위바위보 승패를 판단하는 코드
rsp('가위','바')
python raise.py
Traceback (most recent call last):
File "raise.py", line 11, in <module>
rsp('가위','바')
File "raise.py", line 9, in rsp
raise ValueError
ValueError
def rsp(mine, yours): # 나와 , 상대방
allowed = ['가위','바위', '보']
if mine not in allowed: # mine 에 '가위', '바위', '보' 중에 있는지 검사
raise ValueError # 없으면 ValueError 발생
if yours not in allowed: # yours 에 '가위', '바위', '보' 중에 있는지 검사
raise ValueError # 없으면 ValueError 발생
try:
rsp('가위', '바')
except ValueError:
print('잘못된 값을 넣었습니다.')
반복문이 중첩 되어있을때 - raise
# 반 안에 190이 넘는 학생이 있으면 반 이름을 출력하고 즉시, 프로그램을 종료한다.
school = {'1반': [172, 185, 198, 177, 165, 199], '2반':[165, 177, 167, 180, 191]}
for class_number, students in school.items():
# class_number 에는 '반이름' , students 에는 [학생들의 키 list]가 대입된다.
for student in students:
if student>190:
print(class_number, '반에 190을 넘는 학생이 있습니다.')
break
python raise.py
1반 반에 190을 넘는 학생이 있습니다.
2반 반에 190을 넘는 학생이 있습니다.
school = {'1반': [172, 185, 198, 177, 165, 199], '2반':[165, 177, 167, 180, 191]}
try:
for class_number, students in school.items():
for student in students:
if student>190:
print(class_number, '반에 190을 넘는 학생이 있습니다.')
raise StopIteration
# 예외가 try: 블럭에 있지 않으면 에러 발생시 프로그램이 멈춘다.
except StopIteration:
print('정상종료')
python raise.py
1반 반에 190을 넘는 학생이 있습니다.
정상종료