본문 바로가기

Python 기초

파이썬 기초(17)-예외처리

*이 글을 읽기전에 작성자 개인의견이 있으니, 다른 블로그와 교차로 읽는것을 권장합니다.*

1. 예외

예외(Exception)프로그램 실행 중 발생할 수 있는 예상치 못한 문제 또는 오류 상황을 의미합니다. 예외가 발생하면 프로그램은 중단되기 때문에 이를 적절하게 처리하여 중단을 방지하거나 오류에 대한 정보를 사용자에게 제공해야 합니다.

2. 예외 발생 경우

try:
    # 예외가 발생할 가능성이 있는 코드

except ExceptionType1:  # 'ExceptionType1'에는 실제 예외 유형이 들어갑니다.
    # ExceptionType1 예외가 발생했을 때 실행될 코드

except ExceptionType2:  # 'ExceptionType2'에는 다른 예외 유형이 들어갑니다.
    # ExceptionType2 예외가 발생했을 때 실행될 코드

# 추가적인 except 블록을 계속 추가할 수 있습니다.

else:
    # try 블록에서 예외가 발생하지 않았을 때 실행될 코드

finally:
    # 예외 발생 여부와 관계없이 항상 실행될 코드

예외 종류)

  • SyntaxError: 잘못된 문법
  • ValueError: 함수나 연산에 잘못된 값 접근
  • TypeError: 올바르지 않은 유형의 객체 접근
  • ZeroDivisionError: 숫자를 0으로 나눌때
  • IndexError: 시퀀스(자료형)에 잘못된 인덱스 접근
  • KeyError: 딕셔너리 자료형에서 존재하지 않는 키 접근
  • AttributeError: 객체의 속성 or 메서드 잘못된 접근
  • FileNotFoundError: 존재하지 않는 파일 접근
  • ImportError: 존재하지 않는 모듈, 모듈의 속성, 함수에 대한 접근
  • NameError: 정의되지 않은 변수, 함수에 접근
  • OverflowError: 수치 결과가 컴퓨터의 처리 감당불가능한
  • MemoryError: 사용 메모리 소진

예외처리 기법으로 크게 3가지로 나뉠 수 있습니다.

2-1. 모든 예외 처리

try:
	오류코드
except [오류클래스]:
	...
    
    
#또는

try:
	오류코드
except :
	...

ZeroDivisionError 발생오류

exception클래스는 모든 오류클래스를 대변합니다. 또한 except문만 사용할 때, exception은 기본값으로 설정되어있기 때문에, exception클래스는 생략해서 사용가능합니다. 주로 웹사이트를 제작할 때 사용하는데, 대부분의 상황에선 exception을 활용한 예외 처리는 권장되지 않습니다.

#try-except문
try:
    print(5/0)
except :    #exception클래스 생략해서 사용
    print('숫자를 0으로 못나눌때')
print('종료')

except만 사용할 경우

2-2. 특정 오류만 예외 처리

try-except문에서 except [오류클래스]를 이용해서 특정 종류의 오류만 예외처리해서 출력합니다.

#try-except문
try:
    print(5/0)
except ZeroDivisionError:
    print('숫자를 0으로 못나눌때')
print('종료')

except ZeroDivisionError 입력

2-3. except [오류클래스] as e

as e를 오류클래스 뒤에 붙인다면, e를 변수로써 사용하여 오류내용을 저장합니다.

IndexError

# as e 사용
#try-except문
try:
    data=[1,2,3,4,5]
    print(data[10])
    print(data[2])  #실행안됨
except IndexError as e:
    print('인덱스오류', e)
print('끝')

as e 는 1번만 사용(출력)합니다.

try:
    data=[10,20,30,40,50]
    print(data[0])
    print(int('일'))    #e1
    print(5/0)          #e2
    print(data[5])      #e3
    print(data[3])
except IndexError as e1:
    print(e1)
    print('인덱스 지정이 올바르지 않습니다')
except ZeroDivisionError as e2:
    print(e2)
    print('0으로 나눌 수 없습니다')
except Exception as e3:
    print(e3)
    print('인덱스지정')
print('프로그램을 종료합니다')

2-4. 예외가 발생하지 않을 경우, 예외 발생과 상관없이 실행

try-else문을 이용하여 예외가 발생하지 않은 경우도 처리합니다. try-finally문을 이용해 예외 발생 여부와 상관없이 실행시킵니다.

#오류상황
data=[10,20,30,40,50]
print(data[2])
print(data(int('일'))) #ValueError
print(5/0)             #ZeroDivisionError
print(data[5])         #IndexError
#오류 예외처리
try:
    data=[10,20,30,40,50]
    print(data[2])
    print(data(int('일'))) #ValueError
    print(5/0)             #ZeroDivisionError
    print(data[5])         #IndexError
except ValueError as e:
    print(e)
except ZeroDivsionError:
    print(e)
except IndexError:
    print(e)
else:                  #예외 발생하지 않은 경우도 처리
    print('정상 진행')
finally:               #예외 발생여부 상관없이 처리
    print('오류 상관없이 진행')
print('종료')

3. Exception 클래스

Exception 클래스는 파이썬의 내장 예외 계층 구조에서 거의 모든 내장 예외의 기본 클래스입니다. 이 클래스는 사용자 정의 예외를 만들거나 특정 예외 유형을 잡기 위한 기본적인 인터페이스를 제공합니다.

  • 상속: 예외 유형은 Exception을 상속받아서 정의됩니다. 예를 들면 ValueError, TypeError, FileNotFoundError 등이 있습니다. 이 상속 구조 덕분에 except Exception 블록은 Exception을 상속받은 모든 예외를 캡처할 수 있습니다.
  • 메시지: 예외가 생성될 때, 일반적으로 오류 메시지를 함께 전달할 수 있습니다. 이 메시지는 예외 객체의 args 속성을 통해 접근 가능하며, 예외를 문자열로 변환할 때(예: str(e)) 해당 메시지가 반환됩니다.

raise문을 이용해 인위적인 에러 발생

#에러를 직접 발생
try:
    raise Exception('에러 직접발생')
except Exception as e:
    print(e)

raise문은 에러를 직접 발생시키는 문법으로써, 사용자 정의 에러를 생성합니다. 예외가 발생했을때, 예외처리 문구를 넣을 위치는 상관없습니다.

#예외처리의 위치는 어디서 하던 상관없다.
def func1():
    try:
        func2() #함수 func2()연결
    except TypeError:
        print('타입이 올바르지 않습니다')

def func2():
    try:
        func3() #함수 func3()연결
    except TypeError:
        print('타입이 올바르지 않습니다')

def func3():
    try:
        print('%d' % '문자열')  #문자열 출력
#TypeError: %d format: a real number is required, not str
    except TypeError:
        print('타입이 올바르지 않습니다')

try-except문법을 이용한 예외처리의 위치는 func2(), func3()에 각각 들어갔습니다.

try:
    func1()
except TypeError:
    print('타입이 올바르지 않습니다')

func1()

추가로 func1()안에도 예외처리가 들어감으로써, 출력할 때 예외처리 된 상태로 출력됩니다.

그림으로 표현했을 때

4. 사용자 정의 예외 클래스 직접 활용

Exception 상속을 이용해 class문을 작성합니다. 작성된 class문을 이용해,

class AgeLimitError(Exception): #Exception 상속
    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,'나이 범위보다 어림') #AgeLimitError라는 클래스 생성
        elif age > 50:
            raise AgeLimitError(age,'나이 범위보다 큼')
        else:
            return '나이 범위안에 포함'
ages=[17,60,46,20,52,26]

for age in ages:    #ages시퀀스로 age변수가 있는 조건문이 있는 반복문 생성
    try:
        print(check_age(age))
    except AgeLimitError as e: 
        print(f'Error for age{e.age}: {e}') # e.age는 ages시퀀스안에 있는 숫자중 
        #조건문에 해당되는 인덱스값 출력, e는 오류사유 객체