Programming Language/Python

[Python] 기본 문법(13): 예외 처리 try-except문, Exception, as, specion/dounder method(init, str, len, contains), finally

lxvxxu 2024. 7. 21. 02:31

프로그램에 문제가 생겼을 때 어떻게 대처할 수 있을 것인가?

 

예외(exception) 처리

 

오류: 예상치 못한 실수 or 잘못된 무언가

예외 처리: 오류 상황에 대처하는 것

오류 상황을 어떻게 처리하느냐에 따라 완성도가 높고 사용하기 편리한 프로그램이 되거나 갑자기 응답 없음 상태로 있다가 강제 종료돼서 모든 작업이 수포로 돌아가는 프로그램이 될 수도 있다.

 

 

try-except문

 

형식
try:
    실행할 명령1 ( try문의 하위 명령문 )
    실행할 명령2
     . . .
except 오류 종류:
    예외 처리 명령1
    예외 처리 명령2
     . . .

 

예시

try:
    print("나누기 전용 계산기입니다.")
    num1 = int(input("첫 번째 숫자를 입력하세요 : "))
    num2 = int(input("두 번째 숫자를 입력하세요 : "))
    print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
    print("오류 발생! 잘못된 값을 입력했습니다.")

 

 


as문

예외 처리마다 메시지를 직접 작성하기 귀찮음.

그래서 오류가 발생할 때 표시하는 오류 메시지를 가져와 출력하도록 예외 처리를 할 수 있는 as문이 있다.

 

아래와 같이 예외 처리를 작성하면 as 뒤에 지정한 변수명으로 오류 메시지를 확인할 수 있다.

형식
try:
    실행할 명령1 ( try문의 하위 명령문 )
    실행할 명령2
     . . .
except 오류 종류:
    예외 처리 명령1
    예외 처리 명령2
     . . .
except 오류 종류2 as 변수명:
    예외 처리 명령1
    예외 처리 명령2
     . . .

 

예시

try:
    print("나누기 전용 계산기입니다.")
    num1 = int(input("첫 번째 숫자를 입력하세요 : "))
    num2 = int(input("두 번째 숫자를 입력하세요 : "))
    print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
    print("오류 발생! 잘못된 값을 입력했습니다.")
except ZeroDivisionError as err:
    print(err)

 

 

 

except Exception as err:

모든 오류에 대한 예외 처리를 프로그램 안에 작성하려면 코드가 한없이 길어진다.

그래서 코드 마지막에 다음과 같이 구문을 추가하면 지금까지 정의하지 않은 모든 오류를 예외 처리할 수 있다.

 

try:
    print("나누기 전용 계산기입니다.")
    nums = []
    nums.append(int(input("첫 번째 숫자를 입력하세요 : ")))
    nums.append(int(input("두 번째 숫자를 입력하세요 : ")))
    # nums.append(int(nums[0] / nums[1]))
    print("{0} / {1} = {2}".format(nums[0], nums[1], nums[2]))
except ValueError:
    print("오류 발생! 잘못된 값을 입력했습니다.")
except ZeroDivisionError as err:
    print(err)
except Exception as err:
    print("알 수 없는 오류가 발생했습니다.")
    print(err)

 

 

Exception : 예외 처리 클래스들의 부모 클래스

ValueError, ZeroDivisionError, IndexError

NameError (변수명이 없을 때 발생)

SyntaxError (문법 오류가 있을 때 발생)

FileNotFoundError (접근하려는 파일이 없을 때 발생)

※ 예외 처리를 위해 파이썬에 미리 정의되어 있는 클래스

 


raise 오류 종류

지금까지 발생한 오류는 파이썬에 형태가 미리 정의되어 있는 오류이다.

직접 작성한 프로그램에서 허용하지 않는 동작을 하려고 할 때도 의도적으로 오류를 발생시킬 수 있다.

형식
raise 오류 종류

 

 

예시

try:
    print("한 자리 숫자 나누기 전용 계산기입니다.")
    num1 = int(input("첫 번째 숫자를 입력하세요 : "))
    num2 = int(input("두 번째 숫자를 입력하세요 : "))
    if num1 >= 10 or num2 >= 10: # 입력받은 수가 한 자리인지 확인
        raise ValueError
    print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
    print("값을 잘못 입력했습니다. 한 자리 숫자만 입력하세요.")

 


사용자 정의 예외 처리하기

위 raise는 파이썬에서 이미 정의된 오류를 의도적으로 발생시킨 것이다.

오류도 직접 사용자가 정의해 예외 처리할 수 있는 방법을 알아보자.

 

먼저 두 자리 이상의 수를 입력할 때 발생하는 오류라는 의미로 BigNumberError라는 클래스를 만든다.

그런데!!

코드에서 새로운 오류를 정의해 예외 처리하려면 파이썬에 포함된 Exception이라는 클래스를 상속해야 한다.

 

※ Exception

예외 처리를 위해 파이썬에 미리 정의되어 있는 예외 처리 클래스들의 부모 클래스

 

class BigNumberError(Exception): # 사용자 정의 오류
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return "[오류 코드 001] " + self.msg # 오류 메시지 가공
try:
    print("한 자리 숫자 나누기 전용 계산기입니다.")
    num1 = int(input("첫 번째 숫자를 입력하세요 : "))
    num2 = int(input("두 번째 숫자를 입력하세요 : "))
    if num1 >= 10 or num2 >= 10: # 입력받은 수가 한 자리인지 확인
        # 자세한 오류 메시지
        raise BigNumberError("입력값 : {0}, {1}".format(num1, num2))
    print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
    print("값을 잘못 입력했습니다. 한 자리 숫자만 입력하세요.")
except BigNumberError as err: # 사용자 정의 예외 처리
    print("오류가 발생했습니다. 한 자리 숫자만 입력하세요.")
    print(err) # 오류 메시지 출력

 

 

 

special method (스페셜 메서드) = dunder method (던더 메서드)

dunder metohd = double underscore method

__init__()나 __str__()처럼 이름 앞뒤로 언더바(_)가 2개씩 붙은 형태의 메서드

특별한 역할을 수행하기 위해 별도 처리를 하는 메서드

 

__init__() 메서드 : 객체가 생성될 때 자동으로 호출

__str__() 메서드 : print() 함수로 객체를 출력할 때 호출

__len__() 메서드 : 객체 길이를 구할 때 호출

__contains__() 메서드 : 객체가 특정 요소를 포함하는지 확인할 때 호출


 

finally

try문에서 오류가 발생하든 말든 try문을 벗어나는 시점에서 무조건 실행되는 구문

형식
try:
    실행할 명령1 ( try문의 하위 명령문 )
    실행할 명령2
     . . .
except 오류 종류:
    예외 처리 명령1
    예외 처리 명령2
     . . .
except 오류 종류2 as 변수명:
    예외 처리 명령1
    예외 처리 명령2
     . . .
finally:
    실행할 명령1 ( try문의 하위 명령문 )
    실행할 명령2
     . . .

 

예시

class BigNumberError(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg

try:
    print("한 자리 숫자 나누기 전용 계산기입니다.")
    num1 = int(input("첫 번째 숫자를 입력하세요 : "))
    num2 = int(input("두 번째 숫자를 입력하세요 : "))
    if num1 >= 10 or num2 >= 10:
        raise BigNumberError("입력값 : {0}, {1}".format(num1, num2))
    print("{0} / {1} = {2}".format(num1, num2, int(num1 / num2)))
except ValueError:
    print("값을 잘못 입력했습니다. 한 자리 숫자만 입력하세요.")
except BigNumberError as err:
    print("오류가 발생했습니다. 한 자리 숫자만 입력하세요.")
    print(err)
finally: # 오류 발생 여부와 상관없이 항상 실행
    print("계산기를 이용해 주셔서 감사합니다.")