Python

예외처리

gudwns5533 2026. 5. 29. 17:20
예외

 

예외(Exceptioin)는 프로그램 실행 중 발생할 수 있는 예상치 못한 문제 또는 오류 상황을 의미한다.

예외가 발생하면 프로그램은 중단되기 때문에 이를 적절하게 처리하여 중단을 방지하거나 오류에 대한 정보를 사용자에게 제공해야 한다.

int(10 / 3)
print(5 / 0)
print(4 / 2)

# ZeroDivisionError: division by zero
# 둘째줄 코드에서 예외가 발생하고 프로그램은 세번째줄로 넘어가지않고 중단된다.

예외 계층 구조

 

BaseException

BaseException
 ├── Exception        ← 우리가 보통 사용하는 예외
 │    ├── ValueError
 │    ├── TypeError
 │    ├── ZeroDivisionError
 │    └── ...
 ├── KeyboardInterrupt
 └── SystemExit

 

👉 BaseException이 따로 있는 이유는 “진짜 에러”와 “프로그램 제어용 이벤트”를 구분하기 위해서이다.

 

1. Exception

코드 실행 중 발생한 일반적인 오류

  • 0으로 나누기
  • 잘못된 타입
  • 값 오류

2. KeyboardInterrupt

사용자가 Ctrl + C 눌렀을 때 발생

👉 프로그램을 강제로 멈추는 신호

 

3. SystemExit

프로그램 종료 요청

👉 내부적으로 exit() 호출 시 발생

👉 KeyboardInterrupt와 SystemExit는 사실 '에러'가 아니라 프로그램을 멈추거나 종료하기 위한 신호


예외 처리 기본 구조
try:
    # 예외가 발생할 가능성이 있는 코드
except ExceptionType1:  # 'ExceptionType1'에는 실제 예외 유형이 들어갑니다.
    # ExceptionType1 예외가 발생했을 때 실행될 코드
except ExceptionType2:  # 'ExceptionType2'에는 다른 예외 유형이 들어갑니다.
    # ExceptionType2 예외가 발생했을 때 실행될 코드
# 추가적인 except 블록을 계속 추가할 수 있습니다.
else:         # 필수 x
    # try 블록에서 예외가 발생하지 않았을 때 실행될 코드
finally:      # 필수 x
    # 예외 발생 여부와 관계없이 항상 실행될 코드
try:
    raise KeyboardInterrupt       # raise: 예외를 강제로 발생시키는 코드
except Exception:
    print("Exception 잡힘")
except BaseException:
    print("BaseException 잡힘")

 

👉 이때 except BaseException: 을 except:로 사용한다면 시스템을 정상적으로 종료해야하는 신호까지 모두 막아버릴 수 있으므로 생략해선 안된다.

 

raise

 

raise는 파이썬에서 의도적으로 예외를 발생시키거나(throw), 현재 발생한 예외를 다시 전달(re-raise)하기 위해 사용하는 키워드이다. 이를 통해 잘못된 입력이나 비정상적인 상태를 명확하게 알리고, 호출한 쪽에서 적절히 처리하도록 흐름을 제어할 수 있다.

 

파이썬 주요 예외 타입 정리

try:
    data = [10, 20, 30, 40, 50]
    # print(data[5])        -> IndexError
    # print(int('안녕'))    -> ValueError
    # print(5 / 0)          -> ZeroDivisionError
except IndexError:
    print('인덱스 오류')
except ValueError:
    print('입력 오류')
except ZeroDivisionError:
    print('0으로 나눌 수 없음')
except Exception:
    print('예외 발생!')
else:
    print('에러가 발생하지 않은 정상적인 프로그램')
finally:
    print('에러에 관계없이 무조건 실행되는 문장')
print('프로그램을 종료합니다')

예외 객체 내부 구조
Exception 객체
├── args            → 에러 메시지
├── __str__()       → 사용자용 메시지
├── __repr__()      → 개발자용 표현
├── __class__       → 에러 타입
└── __traceback__   → 에러 발생 위치 정보

 

1. args (에러 메세지 튜플)

 

예외 객체를 생성할 때 전달한 인자(Arguments)들이 담기는 튜플이다. 보통은 에러의 원인을 설명하는 문자열 메세지가 들어간다.

 

2. __str__() (사용자용 메세지)

 

사용자가 읽기 좋은 형태로 에러 메세지를 문자열로 반환해 주는 메서드.

 

3. __repr__() (개발자용 공식 표현)

 

이 객체가 어떤 클래스의 객체이고, 어떤 인자를 가지고 생성되었는지 명확하게 보여주는 개발자용 문자열. 주로 디버깅이나 로그(Log)를 남길 때 유용하다.

 

4. __class__ (에러 타입)

 

이 예외 객체가 정확히 어떤 에러 클래스(타입)에 속하는지 알려준다. 에러의 종류에 따라 로그를 다르게 남기거나 분기 처리를 하고 싶을 때 활용한다.

 

5. __traceback__ (에러 발생 위치 및 경로)

 

코드가 실행되다가 정확히 몇 번째 줄에서, 어떤 함수들을 거쳐 에러가 났는지에 대한 발자취(Traceback 객체)를 담고 있다. 그냥 출력하면 객체 주소만 보이기 때문에, 파이썬의 내장 모듈인 traceback과 함께 사용하면 리포트 형태로 출력된다.

import traceback

try:
    int("abc")
except Exception as e:    # as는 발생한 예외 객체를 변수로 받아서, 그 안에 담긴 정보를 활용하기 위함.
    print("에러 메시지:", e)
    print("에러 타입:", type(e))
    print("args:", e.args)
    print(e.__str__())
    print(e.__repr__())
    print(e.__class__)
    print(e.__traceback__)
    traceback.print_tb(e.__traceback__)
    
# 에러 메시지: invalid literal for int() with base 10: 'abc'
# 에러 타입: <class 'ValueError'>
# args: ("invalid literal for int() with base 10: 'abc'",)
# invalid literal for int() with base 10: 'abc'
# ValueError("invalid literal for int() with base 10: 'abc'")
# <class 'ValueError'>
# <traceback object at 0x000001FD7D205840>
#   File "C:\Users\Administrator\AppData\Local\Temp\ipykernel_324\1305646378.py", line 4, in <module>
#     int("abc")
def func1():
    func2()
    # try:
    #     func2()
    # except TypeError:
    #     print('타입이 올바르지 않습니다')

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

def func3():
    print('%d' % '문자열')
    # try:
    #     print('%d' % '문자열')
    # except TypeError:
    #     print('타입이 올바르지 않습니다')

# func1()

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

 

👉 func3에서 에러가 발생하면 이를 해결할 try-except가 있을 때까지 func3 → func2 → func1 → 호출부 순서로 에러를 위로 전파한다. 따라서 어느 부분에서 예외처리를 해도 상관이 없다.

'Python' 카테고리의 다른 글

모듈  (0) 2026.06.01
매직 메서드  (0) 2026.05.29
객체지향 프로그램 4대 패러다임  (1) 2026.05.28
객체지향 프로그래밍  (0) 2026.05.28
사용자 정의 함수 part2  (0) 2026.05.28