Exception Handling

yong·2025년 5월 6일

SW 모빌리티 스쿨

목록 보기
3/11

25/05/02 수업 내용 정리

Exception Handling

파이썬은 예외처리를 강제하지 않는다. 하지만 외부 자원을 사용하는 경우 자원의 현재 상태를 알 수 없기 때문에 예외처리를 꼭 해줘야 한다.

  • 예외가 발생한 경우에 로깅을 심어두면 문제 상황을 빠르게 확인할 수 있다.

오류의 종류

  • 컴파일 에러 : 문법적인 오류로 실행이 되지 않는 오류
  • 예외 : 실행 도중 외부 요인이나 잘못된 입력 등으로 발생하는 오류
  • 논리적 에러 : 런타임 시에 에러가 발생하지는 않고 정상적으로 실행이 되었지만 의도하지 않는 결과가 나오는 경우
  • 단언 : 개발자가 특정 조건을 만족하지 않으면 고의적으로 실행을 중단시키는 것
    ex 앱 설치시 탈옥된 기기를 막기 위해 단언 처리

예외 처리를 하는 이유

  • 프로그램이 정상적으로 종료되도록 하기 위해
  • 예외가 발생하더라도 프로그램을 계속 수행하기 위해
  • 정상적인 값으로 수정해서 수행하기 위해
  • 예외 내용을 기록하기 위해(로깅)

예외처리 방법

1. try-except 구문

def ten_div(x: int) -> float :
    return 10/x

# 예외처리를 해주지 않으면 에러가 나면서 프로그램이 정상 종료되지 X
print(ten_div(5))
print(ten_div(0))
print("정상종료")
# >> 2.0
# >> ZeroDivisionError: division by zero

# 예외가 발생하더라도 프로그램이 정상적으로 종료됨
print(ten_div(5))
try :
    print(ten_div(0))
except :
    print("예외발생")
print("정상종료")
# >> 2.0
# >> 예외발생
# >> 정상종료

특정한 형태의 예외만 처리하고자 하는 경우에는

  • 예외 클래스 이름을 except 구문에 추가하여 처리한다.
  • 예외 클래스 이름을 추가해서 작성하는 경우에는 except를 여러 개 연속해서 사용해도 된다.
  • except는 if처럼 동작하기 때문에 클래스 이름이 없는 경우를 맨 앞에 놓으면 안된다.
# ZeroDivisionError가 아닌 예외는 처리되지 않음
try :
    print(ten_div("5"))
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
print("정상종료")
# >> TypeError: unsupported operand type(s) for /: 'int' and 'str'
# => 여러 개의 예외 클래스를 추가할 수 있음

# 다음과 같이 예외 클래스를 명시하지 않은 except 문이 먼저 나와서는 안됨
try :
    print(ten_div(0))
except :
    print("앞에서 처리하지 못한 예외를 처리")
except TypeError: # >> 명명된 except 절은 catch-all except 절 뒤에 나타날 수 없다.
    print("예외 발생")
except ZeroDivisionError: # >> 명명된 except 절은 catch-all except 절 뒤에 나타날 수 없다.
    print("0으로 나눌 수 없습니다.")
print("정상종료")
 

예외 클래스 계층은 다음 문서를 참고 : https://docs.python.org/ko/3/library/exceptions.html

  • else 절에 예외가 발생하지 않을 때 수행할 코드를 작성
  • finally는 예외 발생 여부에 상관없이 수행할 문장을 작성
def ten_div(x: int) -> float :
    return 10/x

print(ten_div(5))
try :
    print(ten_div(10))
except TypeError :
    print("자료형이 잘못되었습니다.")
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
except :
    print("앞에서 처리하지 못한 예외를 처리")
else :
    print("예외가 발생하지 않았을 때 처리")
finally :
    print("무조건 수행되는 처리")
print("정상종료")
# >> 2.0
# >> 1.0
# >> 예외가 발생하지 않았을 때 처리
# >> 무조건 수행되는 처리
# >> 정상종료

강제로 예외 발생
raise 예외처리클래스이름(”메시지”)

assertion(단언)을 요즘에는 이렇게 처리한다.

예외 객체를 사용하고자 하는 경우
except 예외 클래스 이름 as 변수명
에러 메시지를 처리하고자 하는 경우에는 예외 클래스 다음에 as 변수명을 설정해서 출력할 수 있다.

def ten_div(x: int) -> float :
    if x == 10 :
        raise Exception("강제로 예외 발생")
    return 10/x

try :
	ten_div(10)
except Exception as e :
    print(e)
else :
    print("예외가 발생하지 않았을 때 처리")
finally :
    print("무조건 수행되는 처리")
print("정상종료")

# >> 강제로 예외 발생
# >> 무조건 수행되는 처리
# >> 정상종료

2. assertion 만들기

assert 조건식, 에러 메시지

조건식이 False가 되면 AssertionError를 발생시킨다.

  • 보통 나와서는 안되는 조건을 검사할 때 사용한다.
  • assert는 디버깅 모드에서만 실행되고, 파이썬은 기본적으로 디버깅 모드(__debug__의 값이 True)이며, assert가 실행되지 않게 하려면 python에 -O옵션을 붙여서 실행하면 된다.
x = 5
assert x >= 10, "x는 10보다 크거나 같아야 합니다."
# >> AssertionError: x는 10보다 크거나 같아야 합니다.

import platform
assert platform.system() == 'Windows', "Windows에서만 동작합니다."

🔎 문자열을 비교할 때는..
대소문자를 구분하거나, 공백을 포함하지 않는 경우가 많기 때문에 비교를 할 때에는 upper, lower, strip 함수 등을 사용해서 조건을 통일시키고 비교해주자!
ex assert platform.system().upper() == 'WINDOWS', "Windows에서만 동작합니다."

3. 사용자 정의 예외 만들기

사용자 정의 예외를 만들고자 하는 경우에는 예외 클래스를 상속 받아서 상위 클래스의 초기화 메서드를 호출할 때 예외 메시지를 넘겨주면된다.

class NotThreeMultipleError(Exception):    # Exception을 상속받아서 새로운 예외를 만듦
    def __init__(self):
        super().__init__('3의 배수가 아닙니다.')

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

three_multiple()
# << 5
# >> 예외가 발생했습니다. 3의 배수가 아닙니다.
profile
꿈틀꿈틀

0개의 댓글