예외 처리(exception handling)
예외란 프로그램이 정상적으로 실행될 수 없는 상황을 뜻한다.
외부 요인을 통제할 수 없다면, 프로그램 안에 예외 상황에 대한 대응책을 마련해두어야 하는것.
예외 처리의 방법
- if 문 사용
코드를 실행하기 전에 예외 상황을 미리 검사.
예외 정보를 함수 밖으로 전달하기 위해 return 문과 오류 코드작성
입력값 검증이 필요하다. - try 문을 사용
예외 상황을 미리 검사하지 않는다.
예외는 함수 호출과 코드 블록을 저절로 빠져나오며, 원하는 위치에서 처리.
- 예외 처리를 할 때는 if 문과 오류 코드를 이용하기보다는, try 문을 이용하는 것이 좋다.
- 미리 허락을 구하는 것보다 저지른 후에 용서를 구하는 것이 쉽다.
if문으로 예외 처리
문제점
- 오류 코드(예외를 나타내는 값)과 정상 값을 구별하기가 어렵다.
- 함수를 연달아 호출할 때 예외를 함수 밖으로 전달 하기가 불편.
- 오류 코드와 정상 값을 구별하는 문제
함수 안에서 예외 처리를 할 때, 함수는 return 문을 이용해 결과를 반환한다.
그런데 함수 호출 도중에 예외가 발생하면, 예외가 발생한 사실을 함수 밖으로 어떻게 알리는가? - 예외 상황인지 항상 미리 검사해야 함.
- 파이썬에서는 루프가 반복 수행하는 내부 구문 바로 다음에 if 없이도 else구문 추가 가능
for i in range(3):
print('loop : ', i) # 1) 루프반복수행
else :
print('Else statement') # 2) else 구문 추가수행
- for~else 구문에서는 break에 따라 수행여부가 달라진다.
# for~else구분에 break문이 있다면?
for i in range(3):
print('loop : ', i) # 1) 루프반복수행
if i == 1:
break # break는 어떤 영향을 줄 것인가?
else :
print('Else statement') # 2) else 구문 추가수행
- if/else 구문에서 else는 '앞의 구문이 수행되지 않으면 else구문을 수행하시오' 라는 뜻이다.
- try/except 구문 또한 이 구문 앞의 try 구문을 수행하다가 예외발생 시, except 구문을 수행하시오' 라는 뜻이다.
예시 1
0이 아닌 정수값을 입력받아 1을 나눈다. -- 결과: return (1/input(int)
'정수가 아닙니다.'출력하기 -- if input(x) != numeric -- print ('정수가아닙니다')
0일 경우 '0으로 나눌 수 없습니다' 출력하기 f input(x) ==0 -- print ('0으로 나눌 수 없습니다')
# 데이터 입력
print('0이 아닌 정수를 입력해 주세요:', end=' ')
user_string = input()
# 예외 처리: 입력값이 정수가 아닌 경우 프로그램 종료
if not user_string.isnumeric():
print(user_string, '은 정수가 아닙니다.')
exit() # 프로그램 종료
# 입력값(문자열)을 정수로 변환
user_number = int(user_string)
# 예외 처리: 입력값이 0인 경우 프로그램 종료
if user_number == 0:
print('0으로 나눌 수 없습니다.')
exit() # 프로그램 종료
# 결과 출력
print(1 / user_number)
추가
while문을 이용해서 올바른 데이터를 입력 할때 까지 계속 입력을 요청 할 수 있다.
while(True): # ❶ 무한 반복
# 데이터 입력
print('0이 아닌 정수를 입력해 주세요:', end=' ')
user_string = input()
# 예외 처리: 입력값이 정수가 아닌 경우 다시 입력
if not user_string.isnumeric():
print(user_string, '은 정수가 아닙니다.')
continue # ❷ while 문 본문의 시작 지점에서 다시 반복
# 입력값(문자열)을 정수로 변환
user_number = int(user_string)
# 예외 처리: 입력값이 0인 경우 다시 입력
if user_number == 0:
print('0으로 나눌 수 없습니다.')
continue # ❷ while 문 본문의 시작 지점에서 다시 반복
break # ❸ 반복 중지
# 결과 출력
print(1 / user_number)
0이 아닌 정수를 입력해 주세요: 이백
이백 은 정수가 아닙니다.
0이 아닌 정수를 입력해 주세요: 0
0으로 나눌 수 없습니다.
0이 아닌 정수를 입력해 주세요: 200
0.005
try 문 : 잠재적인 예외 처리하기
장점: if문의 문제를 모두 해결함
- 정상 값과 구별하기 어려운 오류 코드 대신, 예외 객체라는 특별한 정보로 예외를 전달할 수 있다.
- 함수 호출속에서 예외가 발생하면 예외 객체가 함수 바깥으로 전달된다.
- 예외가 발생할 것을 미리 확인하는 대신, 예외가 발생했을때 처리하는 방법을 따른다.
방법
1. except 예외 종류
try:
예외가 발생할 수 있는 코드 블록
...
except 예외종류:
예외종류에 해당하는 예외가 발생했을 때 실행할 코드 블록
...
(필요에 따라 except 절을 추가로 작성)
2. try문의 else절을 이용
else 절에 작성한 코드는 try 문의 본문을 다 실행할 때까지 예외가 발생하지 않은 경우에 실행된다. try 절의 작성 양식에 else 절을 추가
try:
예외가 발생할 수 있는 코드 블록
...
except 예외종류:
예외종류에 해당하는 예외가 발생했을 때 실행할 코드 블록
...
(필요에 따라 except 절을 추가로 작성)
else:
예외가 발생하지 않은 경우 실행할 코드 블록
예시 2
except절을 추가하여 예상 오류코드에 대한 예외 처리 사항을 생성한다.
>>> 1 / 0 : Traceback (most recent call last): File "<prtc>", line 1, in <module> ZeroDivisionError: division by zero
>>> 1 / hey: Traceback (most recent call last): File "<prtc>", line 1, in <module> 1/hey NameError: name 'hey' is not defined
# ❶ try 블록에 예외가 일어날 수 있는 코드를 기술한다.
try:
print('0이 아닌 정수를 입력해 주세요:', end=' ')
user_number = int(input())
print(1 / user_number)
# ❷ 처리해야 할 예외의 이름과 처리방법을 except 블록에 기술한다.
except ZeroDivisionError: # 0으로 나누는 오류 처리
print('0으로 나눌 수 없습니다.')
except ValueError: # int 유형이 될 수 없는 문자열의 오류 처리
print('입력한 값은 정수가 아닙니다.')
# 사전확인했던 오류값이 NameError였지만 try문에 들어가면 valueError로 변경되어 올바른 실행이 안되고 아래와 같으 오류가 나온다.
# except NameError:
# print('입력한 값은 정수가 아닙니다.')
'''Traceback (most recent call last):
File "<prtc>", line 6, in <module>
user_number = int(input())
ValueError: invalid literal for int() with base 10: 'hey''''
추가
while문을 이용해서 올바른 입력은 반복하여 요구하기
while True:
try:
print('0이 아닌 정수를 입력해 주세요:', end=' ')
user_number = int(input())
print(1 / user_number)
break # 예외가 발생하지 않은 경우, 반복을 빠져나간다
except ZeroDivisionError:
print('0으로 나눌 수 없습니다.')
except ValueError:
print('입력한 값은 정수가 아닙니다.')
0이 아닌 정수를 입력해 주세요: 백
입력한 값은 정수가 아닙니다.
0이 아닌 정수를 입력해 주세요: 0
0으로 나눌 수 없습니다.
0이 아닌 정수를 입력해 주세요: 20
0.05
예시 3
try 문에서 else절 사용
while True:
try:
print('0이 아닌 정수를 입력해 주세요:', end=' ')
user_number = int(input())
result = 1 / user_number
except ZeroDivisionError:
print('0으로 나눌 수 없습니다.')
except ValueError:
print('입력한 값은 정수가 아닙니다.')
# 예외가 발생하지 않은 경우에만 실행
else:
print(result) # 결과를 출력하고
break # 반복을 빠져나간다
예시4
try 문을 빠져나온 예외 처리하기
# 블록 1: 바깥쪽 try 문
try:
# 블록 2: while 문
while True:
# 블록 3: 안쪽 try 문
try:
print('0이 아닌 정수를 입력해 주세요:', end=' ')
user_number = int(input())
result = 1 / user_number
except ZeroDivisionError:
print('0으로 나눌 수 없습니다.')
except ValueError:
print('입력한 값은 정수가 아닙니다.')
else:
print(result) # 결과를 출력하고
break # 반복을 빠져나간다
# 바깥쪽의 try 문에서 KeyboardInterrupt 예외를 처리한다
except KeyboardInterrupt:
print('Ctrl + C를 누르셨군요.')
예외가 코드 블록 안에서 발생하는 경우 예외 객체는 가장 가까이 있는 try 문이 처리할 때까지 코드 블록을 차례대로 빠져나간다. 이 특징을 이용하면 함수 호출 안에서 일어난 예외를 함수 호출 밖에서 처리할 수 있다.
- assert '조건', '에러메시지' : 조건이 맞지 않는 경우, 에러메시지(Assertion Error)를 띄워준다.
- assert()는 방어적 프로그래밍(defensive programming) 방법 중 하나이며, 코드를 점검하는데 사용된다.
# 두번째방법. 조건에 맞는 경우, 함수에서 결과값 변수를 반환해주고 break로 빠져나온다.
def variable_return(p_a, p_b):
is_variable = True
for i in range(2, min(p_a, p_b) +1):
if p_a % i == 0 and p_b % i == 0:
is_variable = False
break
return is_variable
# 조건점검
assert variable_return(4,9), '서로소입니다.'
#assert variable_return(3,6), '코드 점검 메시지입니다2.'
assert not variable_return(3,6), '서로소 아닙니다.'
print('variable_return:',variable_return(4,9)) # 변수값 반환
- try / except / raise / finally 구문에 대해서 익혀보자.
- 예외처리를 위한 키워드들이다.
- try : 처리하고자 하는 부분을 넣는다.
- except : try구문 안에서 발생할 것으로 예상되는 예외를 처리한다.
- raise : 예외상황일 때 명시적으로 처리한다.
- finally : 마지막으로 실행하는 코드
- 예외처리를 위한 키워드들이다.
- try / finally : 에러가 발생하더라도 마지막 코드를 수행해야 할때.
- try / except / else : else 구문을 사용하면 예외구분을 위해 try 구문 안에 들어갈 코드를 최소화시켜 가독성이 좋아진다.
# try / raise / except
try:
print('try test')
test = int(input())
if test < 0:
raise NotImplementedError # 예외사항에 대해 처리하는 raise!
print('test2 : ',test)
except NotImplementedError:
print('NotImplemented Error')
ref. https://python.bakyeono.net/chapter-9-3.html
'Computer Science' 카테고리의 다른 글
[Computer Science] 자료구조 - ADT(추상자료형) / linked-list/ Stack / Queue !!! (0) | 2021.10.04 |
---|---|
[Computer Science] 리팩토링과 최적화 -Refactoring, Data Optimization (0) | 2021.09.22 |
[Computer Science] 변수설계 - 지역변수와 전역변수 (0) | 2021.09.21 |
[Computer Science] 컴프리헨션(comprehension) (0) | 2021.09.21 |
[Computer Science] OOP 개념을 활용하여 코드설계 (0) | 2021.09.14 |