IT/파이썬

[코딩도장] day26. 파이썬 예외 처리 사용하기 - try except, else, finally

_하늘여우_ 2020. 9. 20. 00:48

출처 : unsplash

■ 들어가기

- 파이썬 코딩 도장 (남재윤/길벗). 을 공부하며 정리하는 블로그


▶ Unit38. 예외 처리 사용하기

     - 38.1 try except로 사용하기

     - 38.2 else와 finally 사용하기

     - 38.3 예외 발생시키기

     - 38.4 예외 만들기

 

0. 들어가기

- 예외 발생 시 스크립트 중단 없이 계속 실행하게 해주는 예외 처리 방법 학습

- ZeroDivisionError, AttributeError, NameError, TypeError 등등..

 

 

>> 38.1 try except로 사용하기 <<

- 사용법
try :
        실행할 코드
except :
        예외가 발생했을 때 처리하는 코드
목적 : 숫자를 0으로 나누었을 때 발생하는 예외(ZeroDivisionError) 처리
소스 (try_except.py) 결과
try :
    x = int(input('나눌 숫자를 입력하세요: '))
    y = 10 / x
    print(y)
except :    # 예외 발생 시 실행
    print('예외가 발생했습니다.')
나눌 숫자를 입력하세요: 0
예외가 발생했습니다.

- 예외 발생 시, 해당 라인의 코드 실행을 중단하고 바로 except로 가서 코드를 실행

출처 : 파이썬 코딩 도장 (dojang.io)

 

1. 특정 예외만 처리하기

- except에 예외 이름을 지정해서 특정 예외 발생 시에만 처리 코드 실행

- 사용법
try : 
      실행할 코드
except 예외이름 :
    예외가 발생했을 때 처리하는 코드   
목적 : 예외이름을 지정해서 특정 에러 발생 시 처리
소스 (try_except_exception.py) 결과
y = [10, 20, 30]

try :
    index, x = map(int, input('인덱스와 나눌 숫자를 입력하세요: ').split())
    print(y[index] / x)
except ZeroDivisionError :
    print('숫자를 0으로 나눌 수 없습니다.')
except IndexError :
    print('잘못된 인덱스입니다.')
인덱스와 나눌 숫자를 입력하세요: 2 0
숫자를 0으로 나눌 수 없습니다.

인덱스와 나눌 숫자를 입력하세요: 3 5
잘못된 인덱스입니다.

 

2. 예외의 에러 메시지 받아오기

- except에서 as 뒤에 변수를 지정하면 발생한 예외의 에러 메시지 가져올 수 있음

- 보통 변수는 예외(exception)의 e를 따서 사용

- 사용법
try :
      실행할 코드
except 예외 as 변수 :
      예외가 발생했을 때 처리하는 코드
목적 : 변수 지정해서 에러 메시지 취득
소스 (try_except_as.py) 결과
y = [10, 20, 30]

try :
    index, x = map(int, input('인덱스와 나눌 숫자를 입력하세요: ').split())
    print(y[index] / x)
except ZeroDivisionError as e :
    print('숫자를 0으로 나눌 수 없습니다.', e)
except IndexError as e :
    print('잘못된 인덱스입니다.', e)
인덱스와 나눌 숫자를 입력하세요: 2 0
숫자를 0으로 나눌 수 없습니다. division by zero

인덱스와 나눌 숫자를 입력하세요: 3 5
잘못된 인덱스입니다. list index out of range

- 모든 예외의 에러 메시지를 출력하고 싶은 경우 except에 Exception을 지정하고 as 뒤에 변수 입력

( Exception은 에러 메시지의 조상, 모든 예외는 Exception을 상속받아 구현됨 )

except Exception as e :
    print('예외가 발생했습니다 - ', e)

>> 38.2 else와 finally 사용하기 <<

- 예외가 발생하지 않은 경우 코드를 실행하는 else 구현

- else는 except 바로 다음에 와야 함

- try ~ except ~ else 와 같이 사용해야 하며, except 생략 불가

- 사용법
try :
      실행할 코드
except :
      예외가 발생했을 때 처리하는 코드
else :
      예외가 발생하지 않았을 때 실행할 코드
목적 : 예외가 발생하지 않은 경우 처리
소스 (try_exception_else.py) 결과
try :
    x = int(input('나눌 숫자를 입력하세요: '))
    y = 10 / x
except ZeroDivisionError :
    print('숫자를 0으로 나눌 수 없습니다.')
else :
    print(y)
나눌 숫자를 입력하세요: 2
5.0

나눌 숫자를 입력하세요: 0
숫자를 0으로 나눌 수 없습니다.

 

1. 예외와는 상관없이 항상 코드 실행하기

- finally를 사용해서 예외 발생 여부와 상관없이 항상 코드를 실행

- try ~ except ~ else ~ finally 와 같이 사용해야 하며, except와 else 생략 가능

- 사용법
try :
      실행할 코드
except :
      예외가 발생했을 때 처리하는 코드
else :
      예외가 발생하지 않았을 때 실행할 코드
finally :
      예외 발생 여부와 상관없이 항상 실행할 코드
목적 : try의 코드 끝나면 항상 finally 수행
소스 (try_except_else_finally.py) 결과
try :
    x = int(input('나눌 숫자를 입력하세요: '))
    y = 10 / x
except ZeroDivisionError :
    print('숫자를 0으로 나눌 수 없습니다.')
else :
    print(y)
finally :
    print('코드 실행이 끝났습니다.')
나눌 숫자를 입력하세요: 2
5.0
코드 실행이 끝났습니다.

나눌 숫자를 입력하세요: 0
숫자를 0으로 나눌 수 없습니다.
코드 실행이 끝났습니다.

출처 : 파이썬 코딩 도장 (dojang.io)

[참고] try 는 함수가 아니므로 '스택 프레임'을 생성하지 않으며 따라서 try 안에서 생성된 변수를 try 바깥에서 사용가능함!


>> 38.3 예외 발생시키기 <<

- 파이썬에서 정해진 예외가 아닌 개발자가 직접 예외 발생 가능

- 사용법 : raise 예외('에러메시지')
목적 : 임의의 예외 발생
소스 (try_except_raise.py) 결과
try :
    x = int(input('3의 배수를 입력하세요: '))
    if x % 3 != 0 :
        raise Exception('3의 배수가 아닙니다.')
    print(x)
except Exception as e :
    print('예외가 발생했습니다.', e)
3의 배수를 입력하세요: 5
예외가 발생했습니다. 3의 배수가 아닙니다.

- raise로 예외 발생 시 raise 이후 코드는 실행되지 않고 바로 except로 넘어감

 

1. raise의 처리 과정

목적 : raise 처리 과정 확인 (try ~ except 없는 상태)
소스 (try_except_function_raise.py) 결과
def three_multiple() :
    x = int(input('3의 배수를 입력하세요: '))
    if x % 3 != 0 :
        raise Exception('3의 배수가 아닙니다.')
    print(x)



try :
    three_multiple()
except Exception as e :
    print('예외가 발생했습니다.', e)
3의 배수를 입력하세요: 5
예외가 발생했습니다. 3의 배수가 아닙니다.

- three_multiple 함수 안에 try ~ except 가 없는 상태에서 에러 발생하여 함수 바깥의 except에서 예외 처리됨

- 즉, 예외 발생하더라도 현재 코드 블록에서 처리할 except가 없다면 except가 나올 때까지 상위 코드 블록으로 이동

- 최종적으로 처리할 except가 없는 경우 코드 실행 중지 후 에러 발생

 

2. 현재 예외를 다시 발생시키기

목적 : except로 발생한 예외를 raise로 다시 상위 코드 블록에서 다시 예외 처리
소스 (try_except_raise_in_except.py) 결과
def three_multiple() :
    try :
        x = int(input('3의 배수를 입력하세요: '))
        if x % 3 != 0 :
            raise Exception('3의 배수가 아닙니다.')
        print(x)
    except Exception as e :
        print('three_multiple 함수에서 예외가 발생했습니다.', e)
        raise


try :
    three_multiple()
except Exception as e :
    print('스크립트 파일에서 예외가 발생했습니다.', e)
3의 배수를 입력하세요: 5
three_multiple 함수에서 예외가 발생했습니다. 3의 배수가 아닙니다.
스크립트 파일에서 예외가 발생했습니다. 3의 배수가 아닙니다.

√ 대체 이런 코드는 왜 사용하는 걸까?? 


>> 38.4 예외 만들기 <<

- 예외 : 내장된 예외, 사용자 정의 예외

- 사용자 정의 예외 : 프로그래머가 직접 만든 예외

- Exception을 상속받아 새로운 클래스를 만듦

- 사용법
class 예외이름(Exception) :
      def __init__(self) :
          super().__init__('에러메시지')
목적 : 사용자 정의 예외 사용
소스 (exception_class.py) 결과
class NotThreeMultipleError(Exception) :
    def __init__(self) :
        super().__init__('3의 배수가 아닙니다.')

def three_multiple() :
    try :
        x = int(input('3의 배수를 입력하세요: '))
        if x % 3 != 0 :
            raise NotThreeMultipleError
        print(x)
    except Exception as e :
        print('예외가 발생했습니다.', e)


three_multiple()
3의 배수를 입력하세요: 5
예외가 발생했습니다. 3의 배수가 아닙니다.