■ 공부/Python

DAY 8. 예외처리

J U N E 2024. 3. 20. 16:51

exception error에 대한 처리 프로세스

try - except Exception(얘는 생략되어있음)

로 써준다. 

정식적으로는 try - except - else - finally 순으로 작성하지만

else와 finally는 생략가능

try:
    print(10 / 3)
    print(5 / 0)
    print(4 / 2)
except ZeroDivisionError:
    print('0으로 나눌 수 없습니다.')

print('프로그램을 종료합니다.')

 

print(5 / 0) 같은 부분은

오류이므로 zerodivision error가 발생한다.

그럴 때 어떻게 사용자 혹은 유저에게 알려줄까 하는 부분을 구현한다.

 

물론 특정 오류뿐 아니라 자바의 catch (Exception e) 처럼

퉁쳐서 한 방에 적어줄 수도 있다.

try:
    print(10 / 3)
    print(5 / 0)
    print(4 / 2)
except :    #안쓰면 .* 같은 느낌임 . 에러 전체
    print('0으로 나눌 수 없습니다.')

print('프로그램을 종료합니다.')

 

하지만 퉁쳐서 적을 때 주의할 점,

try:
    data = [10, 20, 30, 40, 50]
    print(data[0])
    print(int('일'))
    print(5 / 0)
    print(data[5])
    print(data[3])
except IndexError:
    print('인덱스 지정이 올바르지 않습니다.')
except ValueError:
    print('문자열을 정수로 변환했습니다.')
except ZeroDivisionError:   #순서 상관없이 에러종류가 있기만 하면 됨.
    print('0으로 나눌 수 없습니다.')
except:
    print('오류를 모두 처리합니다.')    #하지만 .*를 상단에 쓴 경우 하단 에러종류들은 실행불가함. 그래서 .*을 쓰려면 최하단에 쓰기
print('프로그램을 종료합니다.')

 

다른 에러들은 순서 상관없이 써 주기만 하면 되지만

except 통으로 써 줄 때는 상단에 기재할 경우 

내꺼만 처리하고 프로그램을 종료시켜 버리기 때문에

이후 구문에 다른 에러가 또 있더라도 그 부분은 확인 못하고 종료가 되어버린다.

그래서 굳이 통으로 써 주고 싶으면 제일 하단에 적도록 한다.

 

try:
    data = [10, 20, 30, 40, 50]
    print(data[0])
    print(int('일'))
    print(5 / 0)
    print(data[5])
    print(data[3])
except IndexError as e:
    print('인덱스 지정이 올바르지 않습니다.')
except ZeroDivisionError as e:
    print('0으로 나눌 수 없습니다.')
except Exception as e:
    print(e)    #객체가 찍힘. str이 작동하기 때문에 에러에 대한 str은 메세지가 찍히게 되어있음.
    #하나로 퉁친다 하더라도 최우선 에러 하나에 대해서만 출력
print('프로그램을 종료합니다.')

 

as 라는 걸 써서 별칭을 써 줄 수 있는데

sql이랑 비슷한 점이 많구만..

요 as는 이따 나중에 파일입출력 with 구문에서도 등장한다.

그런 거 보면 간간히 쓰이는 것 같다.

 

다음 else 사용 예시:

try:
    data = [10, 20, 30, 40, 50]
    print(data[0])
    print(data[3])
except IndexError as e:
    print('인덱스 지정이 올바르지 않습니다.')
except ZeroDivisionError as e:
    print('0으로 나눌 수 없습니다.')
except Exception as e:
    print(e)
else:
    print('정상적인 프로그램 진행') #에러가 안나면 else문 실행
finally:
    print('오류에 관계없이 무조건 실행되는 문장')
print('프로그램을 종료합니다.')

10
40
정상적인 프로그램 진행
오류에 관계없이 무조건 실행되는 문장
프로그램을 종료합니다.

 

else는 오류가 없을 때 실행되는 구문으로

사실 이게 왜 있는지는 의문이다만

(아니.. 오류가 없으면 그냥 진행하면 되지, 굳이...? 라는 느낌)

 

else 블록은 예외가 발생하지 않았을 때 실행되는 코드를 포함하기 위해 사용됩니다. 따라서
예외 처리의 세부 사항과 일반적인 실행 흐름을 명확하게 분리하여 코드를 작성하는 데 도움이 됩니다.
여기에는 몇 가지 이유가 있습니다:

가독성: try 블록에서 예외가 발생할 때 예외 처리 코드를 작성하고, 그렇지 않은 경우
실행될 코드를 else 블록에 작성함으로써 코드의 의도를 명확히 할 수 있습니다.
이는 코드를 읽는 사람이 예외 처리와 일반적인 흐름을 쉽게 이해할 수 있도록 합니다.

분리된 예외 처리: else 블록을 사용하면 예외 처리 코드와 일반적인 실행 코드를 분리할 수 있습니다.
이는 코드의 유지보수를 쉽게 만들어줍니다. 예외 처리 코드를 변경할 때 예외 처리 외의 부분에
영향을 미치지 않도록 보장합니다.

결과 확인: 예외 처리 코드를 작성할 때, 예외가 발생하지 않았을 때 어떤 일이 발생하는지
명확히 이해하고 확인할 수 있습니다. else 블록을 사용하면 정상적인 경우에 어떤 작업을 수행하는지
명시적으로 볼 수 있습니다.따라서 else 블록은 코드의 가독성과 유지보수성을 향상시키는데 도움이 됩니다.

 

오늘도 등장하신 우리 G선생

 

아 뭔가 프로그램 실행.. 이라기 보다

개발자 입장에서 코드를 볼 때 필요한 거구만.

별로 안 쓸 것 같긴 한데 나중에 예시를 보면 명확해 지겠지.


 

■ Exception 클래스

 

파이썬도 마찬가지로 Exception은 클래스로

하위 오류들은 모두 Exception클래스를 상속받고 있다.

 

물론 내가 오류유형을 Exception클래스로부터 상속받아 직접 만들 수도 있음! 

(내가 만든 함수에 대해 특정 오류를 잡아내야 할 필요도 있으므로)

다만 이건 파이썬 자체 오류가 아니라 나만의 오류인 셈이므로

문법만 맞으면 에러는 나지 않는다. 그래서 일부러 예외 발생을 시켜야 하는데

이 때 일부러 예외를 발생시키는 방법으로 raise를 쓴다.

 

class AgeLimitError(Exception): #를 상속받으면 message가 필요함 그래서 자식에 message를 받아서 super 한테 주면서 호출
    def __init__(self, age, message='원하는 나이 범위가 아님'):
        self.age = age
        self.message = message
        super().__init__(message)   #Exception(메세지)

def check_age(age):
    if age < 20:
        raise AgeLimitError(age, '나이 범위보다 어림')  #원래 있는 에러객체가 아닌 새로 만든 에러 종류이기때문에 raise를 써서 일부러 발생시킴
    elif age > 50:
        raise AgeLimitError(age, '나이 범위보다 큼')
    else:
        return '나이 범위 안에 포함'

ages = [17, 60, 46, 20, 52, 26]

for age in ages:
    try:
        print(check_age(age))   #ages의 나이들을 하나씩 check_age에 넣어서 검출
    except AgeLimitError as e:  #AgeLimitError의 모든 객체가 e를 가리킴. AgeLimitError로 만든 객체
        print(f'Error for age {e.age}: {e}')
        


Error for age 17: 나이 범위보다 어림
Error for age 60: 나이 범위보다 큼
나이 범위 안에 포함
나이 범위 안에 포함
Error for age 52: 나이 범위보다 큼
나이 범위 안에 포함

 

raise 사용 예:

 

생성자에서 super().__init__()을 호출하는 이유:

AgeLimitError 객체가 생성이 될 때 자식생성자가 에러메시지를 따로 받게끔 되어있기 때문에

부모생성자의 예외메시지 부분에 내 예외메시지 설정을 전달해줘야 하므로

부모생성자 초기화가 필요하다. 그래서 super를 부르는 것.

 

except AgeLimitError as e: 에서의 별칭 e는

AgeLimitError로 만든 객체로 보면 된다. 그래서

하단 print함수에서 e.age 이런 식으로 부를 수 있는 것

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'■ 공부 > Python' 카테고리의 다른 글

DAY 8-2. 파일 입출력  (0) 2024.03.20
DAY 8-1. 파이썬 모듈  (1) 2024.03.20
DAY 7-2. 스페셜 메소드  (0) 2024.03.20
DAY 7-1. 파이썬 상속  (0) 2024.03.19
DAY 7. 객체지향과 클래스(2)  (0) 2024.03.19