모든 언어가 그렇듯 파이썬에도 에러를 처리해줄 필요가 있다.
1. 에러
에러는 주로 오타로 인한 문법적 실수 에러와 실행중 발생하는 로직적 실수로 나뉜다.
이는 파이썬 말고도 거의 모든 언어에 공통적으로 해당한다.
문법적 실수는 애초에 컴파일 자체가 안 된다.
실행하는 순간 어느 부분에 문제가 있는지 에러메시지가 출력된다.
이건 처리하는데 그렇게 많은 시간이 걸리지 않는다.
중요한 것은 '로직적 실수로 인한 에러'로 이것은 Exception이라고 하는데 이건 언제 어디서 어떻게 발생할지 아무도 예상할 수 없기 때문에 잡아내는 것이 어렵다.
처음 완성한 프로그램이 당장은 아무문제 없이 돌아갈 수는 있어도, 쓰다보면 예상치 못한 에러가 발생하기 마련이며 제 아무리 똑똑한 프로그래머도 이는 피해갈 수 없는 것이 현실이다.
하지만 프로그램을 잘 쓰다가 이런 에러가 발생하면 그 프로그램의 신뢰도는 추락하게 된다.
신뢰할 수 없는 프로그램은 아무도 사용하지 않는다.
때문에 에러를 100% 없앨 수는 없어도 최대한 많은 에러를 예상하고 잡아내는 것이 정말 중요하다고 할 수 있다.
2. try - except
0으로 나누기 에러를 잡아보자
def div(a, b):
return a / b
x, y = input('두 수를 입력하세요 > ').split()
x = int(x)
y = int(y)
try:
print(div(x, y))
except Exception as e:
print(e)
print('최종실행 완료')
함수 div는 a를 b로 나뉘어주는 함수다.
x와 y는 각각 숫자로써 받아오고
try - except를 활용해 x를 y로 나누는 것에 문제가 없는지 확인하고 있다.
이 코드를 실행하고 3과 0을 입력해보자
실행결과
두 수를 입력하세요 > 3 0
division by zero
최종실행 완료
평소같았으면 최종실행 완료 메시지가 뜨지 않는다.
에러가 뜨자마자 모든 코드가 강제종료되기 때문이다.
그러나 예외처리를 해주었기 때문에 division by zero라는 메시지만 띄우고 그 다음 코드를 정상적으로 실행한다.
이번엔 숫자 x와 y를 정상적으로 받아오는지를 확인해보자
여기선 x와 y를 수로만 받아오게 했는데 만약 문자열이나 공백없이 가져온다면 에러가 발생할 것이다.
try:
x, y = input('두 수를 입력하세요 > ').split()
x = int(x)
y = int(y)
except Exception as e:
print(e)
print('최종실행 완료')
이 코드를 실행하고 숫자가 아닌 문자열을 입력해보자
실행결과
두 수를 입력하세요 > asd
not enough values to unpack (expected 2, got 1)
최종실행 완료
보시다시피 에러처리가 잘 되고 있는 것을 알 수 있다.
만약 일반적인 에러처럼 아예 꺼버리고 싶다면 exit()문을 추가해 줄 수 있다.
그런데 exit는 거의 안쓴다고 한다.
그도 그럴게 굳이 그럴 필요가 있나 싶으니...
에러에는 여러가지 종류가 있다.
def div(a, b):
return a / b
x, y = input('두 수를 입력하세요 > ').split()
x = int(x)
y = int(y)
try:
print(div(x, y))
except ZeroDivisionError as e:
print('0으로 나눌 수 없음')
except Exception as e:
print(e)
여기서 보면 except가 두 개가 있는 것을 알 수 있다.
여기서 except ZeroDivisionError 를 굳이 추가해줄 필요는 없다.
그냥 except Exception이 모든 에러를 다 잡아주기 때문이다.
그러나 사용자나 다른사람들의 요구 때문에 에러 종류에 따라 메시지나 처리를 다르게 해야할 수도 있기 때문에 이런걸 사용할 수 있다.
여기서 주의해야할 점은 Exception이 가장 아래에 나와야한다는 것이다.
Exception이 사실상 모든 에러를 다 잡는 상위개념이기 때문에 Exception이 위에 있으면 그 아래 하위 에러처리문은
전부 무시당하기 때문이다.
3. finally
try - except 문의 연장선으로 finally는 try문 내에서 에러가 발생하든 발생하지 않든 무조건 실행하도록 하는 부분이다.
아래 코드를 보자
def div(a, b):
return a / b
x, y = input('두 수를 입력하세요 > ').split()
x = int(x)
y = int(y)
try:
print(div(x, y))
except Exception as e:
print(e)
finally:
print("계산이 완료되었습니다.")
except 다음에 finally가 있는 것을 볼 수 있다.
이 코드를 정상적으로 써보고, 또 에러를 일으켜서 해보자
# 에러를 발생시키지 않는 경우
두 수를 입력하세요 > 3 2
1.5
계산이 완료되었습니다.
# 에러를 발생시킨 경우
두 수를 입력하세요 > 3 0
division by zero
계산이 완료되었습니다.
계산이 완료되었다는 문구가 무조건 나오는 것을 알 수 있다.
finally는 무조건 실행된다.
그런데 except에 코드를 종료시키는 exit를 추가하면 어떨까?
위 코드를 살짝 변형해보자
def div(a, b):
return a / b
x, y = input('두 수를 입력하세요 > ').split()
x = int(x)
y = int(y)
try:
print(div(x, y))
except Exception as e:
print(e)
exit()
finally:
print("계산이 완료되었습니다.")
except에 exit()가 추가되었다.
고로 에러를 일으키면 exit문에 의해 강제로 종료될 것이다.
그렇다면 finally문은 어떻게 될까?
# 실행결과
두 수를 입력하세요 > 3 0
division by zero
계산이 완료되었습니다.
exit가 실행되기 전에 finally가 실행되는 것을 알 수 있다.
이러한 특징은 자바스크립트를 비롯한 타 언어에도 비슷한 형태로 존재한다.
자바스크립트의 경우는 try - catch - finally 의 형태로 사용하는데 자바스크립트도 catch에서 강제종료하기 전에
finally를 실행하는 경우가 있다.
의외로 모르는 사람이 많고 언어마다 미묘한 차이가 있으니 잘 찾아보자
'Language > Python' 카테고리의 다른 글
Python 공부정리 - 주피터 노트북과 json 파일 (0) | 2023.02.07 |
---|---|
Python 공부정리 - 콘솔출력(추가) (0) | 2023.02.06 |
Python 공부정리 - 입출력 (1) | 2023.02.03 |
Python 공부정리 - 패키지, 모듈 (0) | 2023.02.03 |
Python 공부정리 - 객체지향, 클래스 (0) | 2023.02.02 |