[Python] 8. 예외(Exception) 처리

Wonder_Land🛕·2022년 6월 19일
0

[Python]

목록 보기
8/12
post-thumbnail
  1. 구문 오류와 예외
  2. 예외 처리 방법
  3. 예외 객체
  4. 강제로 예외를 발생시키는 방법
  5. Q&A
  6. 마치며

프로그램을 작성하다보면 우리는 탐정이 되어야 하죠🤔

바로 오류가 발생했을 때 입니다.

해결하기 어려운 사건도 존재하듯, 찾지 못하는 오류 하나 때문에 시간과 씨름해야 하죠...

이러한 오류들은
구문오류 : 해석 단계에서 발생
예외 : 실행 단계에서 발생
로 구분됩니다.

오류를 빠르기 확인하기 위해서는, 오류 메시지를 통해 어떤 오류가 발생했는지 살펴보는 습관을 길러야합니다.


1. 구문 오류와 예외

1). 구문 오류(Syntax Error)

  • 구문 오류(Syntax Error)
    : 잘못된 명령을 입력해 발생


    Python의 Interpreter가 해석하지 못해 발생합니다.


    오류 메시지가 알려주는 오타나 문법적으로 필수적인 요소가 빠지진 않았는지를 찾아 재코딩해야 합니다.
print("Syntax Error)	# "를 빼먹음

**[Result]**
SyntaxError: unterminated string literal (detected at line 1)

위의 예시에서는 print()문에서 마지막에 "를 빼먹었습니다.

오류 메시지에서는, 종료되지 않은("가 빠진) string 객체가 있다고 하네요.


2). 예외(Exception)

  • 예외(Exception)
    : 문법적인 문제는 없지만, 실행 중에 예기치 않게 발생

Exception이 발생했을 때 프로그램은 강제 종료되므로, 안전하게 처리해야 합니다.

lst = [1, 2, 3] # 사용가능한 index : 0 ~ 2

print(lst[3])

**[Result]**
IndexError: list index out of range

위의 예시에서, 사용 가능한 index는 0 ~ 2입니다.
하지만 print()문에서 3번 index를 사용했습니다.

오류 메시지에서는, index의 범위를 넘어섰다고 출력하네요.


2. 예외 처리 방법

다음은 사각형의 넓이를 구하는 프로그램입니다.
폭과 높이를 입력받아 넓이를 출력하죠

width = int(input(" 폭 : "))
height = int(input("높이 : "))
area = width * height

print(f'넓이 : {width} * {height} = {area}')

만약 이 때, height로 정수10이 아닌, 1o(숫자 1 + 영어 소문자 o)를 입력하면 어떻게 될까요?

당연히, int()함수를 통해 정수로 변환하는 과정에서 오류메시지가 출력됩니다.

그렇다면, 우리는 이러한 예외를 다루기 위해 어떻게 해야할까요?

한번 알아봅시다.


1) 예외 발생 시 해결 방법

예외 발생 시에는 다음 방법이 있습니다.

  1. if문을 이용한 예외의 처리
  2. try ~ except문을 이용한 예외처리
  3. try ~ except ~ else문을 이용한 예외처리
  4. try ~ except ~ finally문을 이용한 예외처리

1번은, 정상적인 흐름을 제어할 경우에만 사용가능합니다.
즉, 예외가 발생했을 때가 아닌, 예외가 발생할 수 있는 상황을 사전에 제어하는 방식이죠.

2번은 1) 예외가 발생했을 때 사용됩니다.

3번은 1) 예외가 발생했을 때, 2) 예외가 발생하지 않았을 때 사용됩니다.

4번은 1) 예외가 발생했을 때, 2) 예외가 발생하지 않았을 때, 3) 예외 발생과 상관없이 실행할 때 사용됩니다.


(1) if문을 이용한 예외의 처리

width = input(" 폭 : ")
height = input("높이 : ")

if width.isdigit() and height.isdigit():
    area = int(width) * int(height)
    print(f'넓이 : {width} * {height} = {area}')
else :
    print("숫자가 아닌 잘못된 값이 입력되었습니다")

[Result]
폭 : 5
높이 : 1o
숫자가 아닌 잘못된 값이 입력되었습니다

위의 함수에서 사용된 isdigith()입력된 문자열이 숫자 형식인지를 검사합니다.

만약 숫자라면 True를, 아니면 False를 반환하죠

입력된 문자열이 숫자 형식인지를 프로그램 실행 전에 제어하는 방식이죠.


(2) try ~ except문을 이용한 예외처리

이 구문은 try ~구문을 실행하다가 Exception이 생긴 경우,
바로 except블록을 실행하게 합니다. 이 떄, try의 남은 부분은 실행하지 않습니다.

width = input(" 폭 : ")
height = input("높이 : ")

try:
    area = int(width) * int(height)
    print(f'넓이 : {width} * {height} = {area}')
except:	# 예외 발생 시 실행
    print("숫자가 아닌 잘못된 값이 입력되었습니다")

[Result]
폭 : 5
높이 : 1o
숫자가 아닌 잘못된 값이 입력되었습니다

int()함수가 type을 변환하는 과정에서 ValueError가 발생하게 됩니다.

따라서 바로 except문이 실행되고, try의 나머지 부분은 실행되지 않습니다.


(3) try ~ except ~ else문을 이용한 예외처리

width = input(" 폭 : ")
height = input("높이 : ")

try:
    area = int(width) * int(height)
except: # 예외 발생 시 실행
    print("숫자가 아닌 잘못된 값이 입력되었습니다")
else :  # 예외가 발생하지 않았을 시 실행
    print(f'넓이 : {width} * {height} = {area}')

[Result]
폭 : 5
높이 : 1o
숫자가 아닌 잘못된 값이 입력되었습니다

위의 input에서는, Exception이 발생되어 except문이 실행됩니다.

[Result]
폭 : 5
높이 : 10
넓이 : 5 * 10 = 50

위의 input에서는, 제대로 된 값들이 들어와서,
Exception이 발생되지 않아, else문을 실행합니다.


(4) try ~ except ~ finally문을 이용한 예외처리

width = input(" 폭 : ")
height = input("높이 : ")

try:
    area = int(width) * int(height)
except: # 예외 발생 시 실행
    print("숫자가 아닌 잘못된 값이 입력되었습니다")
else :  # 예외가 발생하지 않았을 시 실행
    print(f'넓이 : {width} * {height} = {area}')
finally:
    print("\nfinally문은 예외 발생 여부에 상관없이 실행됩니다.")

[Result]
폭 : 5
높이 : 1o
숫자가 아닌 잘못된 값이 입력되었습니다

finally문은 예외 발생 여부에 상관없이 실행됩니다.

위의 input에서는, Exception이 발생되어 except문이 실행됩니다.
그리고 finally문은 Exception의 여부와 상관없이 실행됩니다.


3. 예외 객체

1) 예외 객체(Exception Object)

  • 예외 객체(Exception Object)
    : 코드를 실행 중 오류가 발생하면 만들어지는 객체로, 오류 발생과 관련한 정보를 가지고 있습니다.
exception (예외) as (객체):

(예외)에는 Exception, ValueException, IndexError 등이 있겠네요
(객체)에는 ex, ve, ie처럼 임의의 Exception Object를 넣어주시면 됩니다.

(1) Exception Object를 참조해 Exception Object의 type과 오류 메시지 확인

width = input(" 폭 : ")
height = input("높이 : ")

try:
    area = int(width) * int(height)
except Exception as ex:	# ex로 참조
    print(type(ex))
    print(ex)
else :
    print(f'넓이 : {width} * {height} = {area}')
finally:
    print("\nfinally문은 예외 발생 여부에 상관없이 실행됩니다.")

[Result]
폭 : 5
높이 : 1o
<class 'ValueError'>
invalid literal for int() with base 10: '1o'

finally문은 예외 발생 여부에 상관없이 실행됩니다.

except Exception as ex를 통해 Exception Object인 ex를 이용해 참조 할 수 있게 됩니다.

(2) 다중 except문을 이용한 Exception Object에 따른 처리의 분기

x = input("x : ")
y = input("y : ")

try:
    result = int(x) / int(y)
except ValueError as ve:    # 숫자가 아닌 값
    print("입력값은 숫자여야 합니다.")
except ZeroDivisionError as ze: # y가 0일 때
    print("나누는 수는 0이 될 수 없습니다.")
except Exception as ex:
    print("예기치 못한 예외가 발생했습니다.")
else:
    print(f'{x} / {y} = {result}')
finally:
    print("\nfinally문은 예외 발생 여부에 상관없이 실행됩니다.")

[Result]
x : 5
y : o
입력값은 숫자여야 합니다.

finally문은 예외 발생 여부에 상관없이 실행됩니다.

ValueError 발생시에는 첫번째 except문을 실행합니다.

[Result]
x : 5
y : 0
나누는 수는 0이 될 수 없습니다.

finally문은 예외 발생 여부에 상관없이 실행됩니다.

ZeroDivisionError 발생시에는 두번째 except문을 실행합니다.

[Result]
x : 5
y : 2
5 / 2 = 2.5

finally문은 예외 발생 여부에 상관없이 실행됩니다.

try문에서 Exception이 발생하지 않으므로,
else문을 실행합니다.


4. 강제로 예외를 발생시키는 방법

1) 강제로 예외를 발생시키는 방법

특정 조건에서 예외 객체를 만들어 예외를 일으킬 수도 있습니다.

이때, 예외 객체의 오류 메시지를 전달할 수 있습니다.

Python에서는 raise문을 이용하여 강제로 예외를 발생시킬 수 있습니다.

다음은 사각형의 면적을 구하는 프로그램입니다.

cal_area()함수에서 숫자가 아닌 값이 매개변수로 전달되면, raise문을 통해 ValueError를 반환합니다.

def cal_area(w, h):
    if w.isdigit() and h.isdigit():
        return int(w) * int(h)
    else :
        raise ValueError("숫자가 아닌 값이 입력되었습니다.")

width = input(" 폭 : ")
height = input("높이 : ")

try:
    area = cal_area(width, height)
except ValueError as ve:
    print(type(ve))
    print(ve)
except Exception as ex:
    print(type(ex))
    print(ex)
else :
    print(f'{width} * {height} = {area}')
finally :
    print("finally문은 예외 발생 여부에 상관없이 실행됩니다.")

[Result]
폭 : 5
높이 : 1o
<class 'ValueError'>
숫자가 아닌 값이 입력되었습니다.

finally문은 예외 발생 여부에 상관없이 실행됩니다.


5. Q&A

-


6. 마치며

오늘은 Exception에 대해 알아봤습니다.

사실 공부를 할 때 접하는 간략한 코드들에서는 Exception을 굳이 다뤄야하나? 싶지만

난이도가 있는 코드를 작성하다보면 정말 예상치도 못한 Error가 많이 나와 Exception을 다뤄주는 것이 좋습니다.

또한, Exception 처리 방법을 익힘으로써 보다 안전하고 견고한 프로그램을 만들 수 있습니다.

내가 어디서 어떻게 틀렸는지 보다 확실하게 확인할 수 있거든요.

학교에서 배울 때 Exception이나 Error와 관련된 부분은 거의 스쳐지나가듯이 배워서,
저도 잘 사용하지 않았습니다.

그런데 다시 공부해보니
'그 때 사용했으면 그나마 편했을텐데...'라는 생각과
그 때 저를 화나게 했던 코드들이 무수히 많이 스쳐지나가네요ㅋㅋㅋ😂

많이 써먹어서 익숙해지면 정말 좋은 역량이 될 거 같아요. 노력하겠습니다 😊

[Reference] : 위 글은 다음 내용을 참고, 인용하여 만들어졌습니다.

  • 전반적 내용 : 삼성 SW Expert Academy
profile
아무것도 모르는 컴공 학생의 Wonder_Land

0개의 댓글