TIL.37 예외처리하기(try, except)
## 예외 처리 사용하기
## 예외(exception) == 코드를 실행하는 중에 발생한 에러를 뜻함
def ten (x):
return 10 / x
print(ten(2))
# 5.0
## 분모를 0으로 넣게 될 경우 실행 젱어가 발생하는데 이런 상황을 예외라고 한다.
print(ten(0))
Traceback (most recent call last):
File "c:/Users/user/Desktop/python3_실습/38.1예외처리사용하기.py", line 9, in <module>
print(ten(0))
File "c:/Users/user/Desktop/python3_실습/38.1예외처리사용하기.py", line 6, in ten
return 10 / x
ZeroDivisionError: division by zero
## ZeroDivisionError뿐만 아니라 지금까지 만난 AttributeError, NameError, TypeError 등
다양한 에러들도 모두가 예외이다.
## try , except 사용하기
## 이러한 예외가 발생했을 때도 스크립트 실행을 중단하지 않고 계속 실행하게 해주는 예외 처리 방법으로
try except가 있다.
# try:
# 실행할 코드
# except:
# 예외가 발생했을 때 처리하는 코드
# 숫자를 0으로 나누었을때 예외 처리
try:
x = int(input('나눌 숫자를 입력하세요: '))
y = 10 / x
print(y)
except: # 예외가 발생했을 때 실행됨
print('예외가 발생했습니다.')
# 나눌 숫자를 입력하세요: 0 (입력)
# 예외가 발생했습니다.
## 위에서는 숫자를 0으로 나눌때 except 예외 처리를 해주었다.
## 특히 예외가 발생하면 해당 줄에서 코드 실행을 중단하고 바로 except로 가서 코드를 실행한다.
## 즉, try의 y = 10 / x 를 비롯하여 그 아래줄에 있는 print(y)도 실행되지 않는다.
## try 의 코드가 예외 없이 잘 실행되면 except의 코드는 실행되지 않고 그냥 넘어간다.

## 특정 예외만 처리하기
## except에 예외 이름을 지정해서 특정 예외가 발생했을 때만 처리 코드를 만들 수 있다.
# try:
# 실행할 코드
# except 예외이름:
# 예외가 발생했을 때 처리하는 코드
y = [10, 20, 30]
try:
index, x = map(int, input('인덱스와 나눌 숫자를 입력하세요: ').split())
print(y[index] / x)
except ZeroDivisionError: # 숫자를 0으로 나눠서 에러가 발생했을 때 실행됨
print('숫자를 0으로 나눌 수 없습니다.')
except IndexError: # 범위를 벗어난 인덱스에 접근하여 에러가 발생했을 때 실행됨
print('잘못된 인덱스입니다.')
# 인덱스와 나눌 숫자를 입력하세요: 2 0
# 숫자를 0으로 나눌 수 없습니다.
# 인덱스와 나눌 숫자를 입력하세요: 3 2
# 잘못된 인덱스입니다.
## except에 예외이름을 지정하여 0으로 나누면 ZeroDivisionError:의 처리 코드가 실행되고
## 인덱스에 3을 지정하면 범위를 벗어나게 됩니다. 이때는 except IndexError:의 처리 코드가 실행된다.
## 예외의 에러 메시지 받아오기
## except 뒤에 as 변수를 지정하면 발생한 예외의 에러 메시지를 확인하여
어떠한 에러가 발생하였는지 확인 할 수 있다.
# try:
# 실행할 코드
# except 예외 as 변수:
# 예외가 발생했을 때 처리하는 코드
## 보통 변수에는 ( exception)의 e를 따서 변수 이름을 e로 작성한다.
y = [10, 20, 30]
try:
index, x = map(int, input('인덱스와 나눌 숫자를 입력하세요: ').split())
print(y[index] / x)
except ZeroDivisionError as e: # as 뒤에 변수를 지정하면 에러를 받아옴
print('숫자를 0으로 나눌 수 없습니다.', e) # e에 저장된 에러 메시지 출력
except IndexError as e:
print('잘못된 인덱스입니다.', e)
# 인덱스와 나눌 숫자를 입력하세요: 2 0
# 숫자를 0으로 나눌 수 없습니다. division by zero
# 인덱스와 나눌 숫자를 입력하세요: 3 2
# 잘못된 인덱스입니다. list index out of range
## 단, 예외가 여러 개 발생하더라도 먼저 발생한 예외의 처리 코드만 실행됩니다
(또는, 예외 중에서 높은 계층의 예외부터 처리된다. 기반 클래스 > 파생 클래스 순)
## 모든 예외의 에러 메시지를 출력하고 싶다면 다음과 같이
except에 Exception을 지정하고 as 뒤에 변수를 넣으면 된다.
except Exception as e: # 모든 예외의 에러 메시지를 출력할 때는 Exception을 사용
print('예외가 발생했습니다.', e)
### 이처럼 예외 처리는 에러가 발생하더라도 스크립트의 실행을 중단시키지 않고 계속 실행하고자 할 때 사용한다.
## 예외 계층
# 예외도 클래스 상속으로 구현되며 다음과 같은 계층으로 이루어져 있습니다. 보통 파이썬에서 새로운 예외를 만들 때는 Exception을 상속받아서 구현한다.
# 전체 계층도는 파이썬 공식 문서를 참조하자.
# Built-in Exceptions: https://docs.python.org/3/library/exceptions.html#exception-hierarchy
Built-in Exceptions — Python 3.9.0 documentation
Built-in Exceptions In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any exception classes derived from that class (b
docs.python.org

## else와 finally 사용하기
## tyr except 문에서 else 사용하기
## 예외가 발생하지 않았을 때 코드를 실행하는 else를 사용해보자
## 다음과 같이 else는 except 바로 다음에 와야 하며 except를 생략할 수 없다. (순서 및 생략 불가)
# try:
# 실행할 코드
# except:
# 예외가 발생했을 때 처리하는 코드
# else:
# 예외가 발생하지 않았을 때 실행할 코드
try:
x = int(input('나눌 숫자를 입력하세요: '))
y = 10 / x
except ZeroDivisionError: # 숫자를 0으로 나눠서 에러가 발생했을 때 실행됨
print('숫자를 0으로 나눌 수 없습니다.')
else: # try의 코드에서 예외가 발생하지 않았을 때 실행됨
print(y)
## 예외가 발생하지 않았알때는 else의 print(y) 실행
## 예외가 발생하였을때는 except의 print('숫자를 0으로 나눌 수 없습니다.') 실행
## try except 문에서의 finally 사용하기
## finally == 예외 발생 여부와 상관없이 항상 코드를 실행하는 한다.
## finally는 except와 else를 생략할 수 있다. (생략 가능)
# try:
# 실행할 코드
# except:
# 예외가 발생했을 때 처리하는 코드
# else:
# 예외가 발생하지 않았을 때 실행할 코드
# finally:
# 예외 발생 여부와 상관없이 항상 실행할 코드
try:
x = int(input('나눌 숫자를 입력하세요: '))
y = 10 / x
except ZeroDivisionError: # 숫자를 0으로 나눠서 에러가 발생했을 때 실행됨
print('숫자를 0으로 나눌 수 없습니다.')
else: # try의 코드에서 예외가 발생하지 않았을 때 실행됨
print(y)
finally: # 예외 발생 여부와 상관없이 항상 실행됨
print('코드 실행이 끝났습니다.')
# 나눌 숫자를 입력하세요: 2
# 5.0
# 코드 실행이 끝났습니다.
# 나눌 숫자를 입력하세요: 0
# 숫자를 0으로 나눌 수 없습니다.
# 코드 실행이 끝났습니다.
## 숫자를 0으로 나누어 예외가 발생하지만 finally의 print('코드 실행이 끝났습니다.')는 항상 실행되는 걸 볼 수 있다.

#### try 안에서 만든 변수는 try 바깥에서 사용할 수 있나요? ####
## try는 함수가 아니므로 스택 프레임을 만들지 않는다.
# 따라서 try 안에서 변수를 만들더라도 try 바깥에서 사용할 수 있다. 물론 except, else, finally에서도 사용할 수 있다.