우리는 프로그램 실행 중에 발행하는 에러는 미리 방지하기 위해 예외처리를 사용한다.
try-except
예외 처리를 위해서 try-except 구문을 사용하며 else 구문은 자주 사용하지 않는다. finally는 파일을 닫아주는 것과 같이 사용한 리소스를 무조건 반환해야 하는 코드가 필요할 때 사용한다.
try-except는 프로그램을 종료하지 않는다는 특성이 있다.
try:
예외가 발생할 수 있는 코드
except:
예외 발생 시 실행할 코드
else:
예외 발생하지 않은 경우 실행할 코드
finally:
항상 실행할 코드
예시로 원화와 환율을 입력 받아 달러값을 반환하는 함수를 만들어 본다.
won = input('원화 금액을 입력하시오.')
dollar = input('환율을 입력하시오.')
try:
print(int(won)/int(dollar))
except:
print('예외가 발생함')
아래와 같이 발생하는 에러를 직접 지정해 줄 수도 있다. e라는 별칭을 주고 print를 하면 에러 메세지도 같이 출력할 수 있다.
won = input('원화 금액을 입력하시오.')
dollar = input('환율을 입력하시오.')
try:
print(int(won)/int(dollar))
except ValueError as e:
print('문자열 예외가 발생함', e)
except ZeroDivisionError:
print('나눗셈의 분모는 0이 불가능함')
else:
print('정상적으로 계산되었습니다.')
finally:
print('항상 실행되는 코드')
예외 계층 구조
아래 예외 계층을 참고하여 try-except 구문을 사용하면 된다. 예를 들어 except OSError 를 사용하면 OSError 하위에 있는 ChildProcessError, FileExistsError,… TimeoutError 가 일어 났을때 모두 커버가 가능하다. 하지만 어떤 예외가 발생하는지 아는 상황에서는 상세히 예외를 적어주는 것이 좋다.
에러 발생시키기
raise 구문은 에러를 강제로 발생시킬 때 사용한다.
raise 예외이름('에러메세지')
에러 메세지는 옵션이다.
num = int(input('음수를 입력하세요.'))
if num >= 0:
raise Exception('양수 입력 불가')
결과
Exception: 양수 입력 불가
try:
num = int(input('음수를 입력하세요.'))
if num >= 0:
raise ValueError('양수 입력 불가')
except ValueError as e:
print('에러 발생', e)
결과
에러 발생 양수 입력 불가
예외 만들기
예외를 직접 만들 때에는 Exception 클래스를 상속받아 새로운 클래스를 만들면 된다.
class 예외이름(Exception):
def __init__(self):
super().__init__('에러메세지')
class PositiveNumberError(Exception):
def __init__(self):
super().__init__('양수 입력 불가')
try:
num = int(input('음수를 입력하세요.'))
if num >= 0:
raise PositiveNumberError
except PositiveNumberError as e:
print('에러 발생!', e)
결과
에러 발생! 양수 입력 불가
NotImplementedError
NotImplementedError는 클래스 상속에 관련된 에러이다. 상위 클래스를 설계할 때 하위 클래스에서 반드시 오버라이드하여 상세하게 구현해야 하는 메소드를 명시하고자 하려면, 해당 메소드의 내용으로 raise NotImplementedError(메시지)를 넣어놓는다.
class BaseWheel:
def roll(self):
raise NotImplementedError('roll 메소드를 구현하세요.')
class MyWheel(BaseWheel):
pass
이렇게 자식클래스를 설계할 때 roll 메소드를 오버라이딩 하지 않으면 NotImplementedError가 발생한다.
>>> mywheel = MyWheel()
>>> mywheel.roll()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in roll
NotImplementedError: roll 메소드를 구현하세요.
하지만 아래와 같이 코드를 수정하면 정상적으로 인스턴스를 생성하고 메서드를 불러올 수 있다.
class BaseWheel:
def roll(self):
raise NotImplementedError('roll 메소드를 구현하세요.')
class MyWheel(BaseWheel):
def roll(self):
print('빠르게 굴러가는 바퀴')
>>> mywheel = MyWheel()
>>> mywheel.roll()
빠르게 굴러가는 바퀴