Data Engineering/python

EP10 | Python 심화 개념 #4 | 예외 처리와 로깅 (Logging & Exception Handling)

ygtoken 2025. 3. 19. 22:44
728x90

이 글에서 다루는 개념

Python에서 예외(Exception) 처리는 프로그램이 예상치 못한 오류로 인해 중단되지 않도록 하는 중요한 개념입니다.
또한, **로깅(Logging)**을 사용하면 프로그램의 동작을 추적하고 디버깅할 수 있습니다.
이번 글에서는 다음 내용을 학습합니다.

  • 예외 처리(try-except-finally)의 개념과 사용법
  • 예외 발생(raise) 및 사용자 정의 예외
  • 로깅(logging 모듈)의 기본 사용법
  • 로깅 레벨과 로그 파일 저장 방법

1️⃣ 예외 처리 (Exception Handling) 기초

🔹 기본 예외 처리 (try-except)

Python에서는 try-except 블록을 사용하여 예외를 처리할 수 있습니다.

try:
    x = 10 / 0  # ZeroDivisionError 발생
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")

📌 예외 처리 흐름

  1. try 블록 실행
  2. 예외 발생 시 except 블록 실행 (정상 실행되면 except 건너뜀)
  3. finally 블록은 항상 실행됨 (선택 사항)

🔹 여러 예외 처리

try:
    num = int("hello")  # ValueError 발생
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
except ValueError:
    print("잘못된 값입니다.")  # 실행됨

🔹 예외 정보 출력 (as e)

try:
    x = 10 / 0
except ZeroDivisionError as e:
    print(f"예외 발생: {e}")  # 예외 메시지 출력

2️⃣ finally 블록과 raise 문

🔹 finally: 항상 실행되는 블록

파일을 열거나 데이터베이스를 연결하는 경우, 예외 발생 여부와 관계없이 반드시 리소스를 정리해야 합니다.

try:
    f = open("example.txt", "r")
    data = f.read()
except FileNotFoundError:
    print("파일을 찾을 수 없습니다.")
finally:
    f.close()  # 항상 실행됨

🔹 raise: 예외 강제 발생

raise 문을 사용하면 특정 조건에서 강제로 예외를 발생시킬 수 있습니다.

def divide(a, b):
    if b == 0:
        raise ValueError("0으로 나눌 수 없습니다.")
    return a / b

try:
    print(divide(10, 0))
except ValueError as e:
    print(e)  # 0으로 나눌 수 없습니다.

3️⃣ 사용자 정의 예외

Python에서 Exception 클래스를 상속하여 **사용자 정의 예외(Custom Exception)**를 만들 수 있습니다.

class NegativeNumberError(Exception):
    pass  # 커스텀 예외 생성

def check_positive(num):
    if num < 0:
        raise NegativeNumberError("음수는 허용되지 않습니다.")

try:
    check_positive(-5)
except NegativeNumberError as e:
    print(e)  # 음수는 허용되지 않습니다.

4️⃣ 로깅(Logging) 기초

print() 대신 logging 모듈을 사용하면 프로그램 실행 정보를 효율적으로 기록할 수 있습니다.

import logging

logging.basicConfig(level=logging.INFO)
logging.info("이것은 정보 메시지입니다.")
logging.warning("이것은 경고 메시지입니다.")
logging.error("이것은 오류 메시지입니다.")

📌 로깅 레벨

  

레벨 의미 예제
DEBUG 상세한 디버깅 정보 logging.debug("디버깅 메시지")
INFO 일반적인 정보 logging.info("정보 메시지")
WARNING 경고 (심각하지 않은 문제) logging.warning("경고 메시지")
ERROR 오류 발생 logging.error("오류 메시지")
CRITICAL 심각한 오류 발생 logging.critical("치명적 오류")

5️⃣ 로그 파일 저장하기

로그를 파일로 저장하려면 filename 옵션을 설정합니다.

import logging

logging.basicConfig(filename="app.log", level=logging.ERROR, format="%(asctime)s - %(levelname)s - %(message)s")

logging.error("파일에 기록된 오류 메시지입니다.")

📌 로그 포맷 지정 옵션

  • %(asctime)s → 시간
  • %(levelname)s → 로그 레벨
  • %(message)s → 메시지

📌 실전 문제: 예외 처리와 로깅 연습하기


문제 1: 0으로 나누기 예외 처리 (try-except)

📌 사용자로부터 두 개의 숫자를 입력받아 나누기 연산을 수행하세요. 0으로 나눌 경우 예외를 처리하세요.

# 🔽 여기에 코드 작성
try:
    a = int(input("첫 번째 숫자: "))
    b = int(input("두 번째 숫자: "))
    result = a / b
    print(f"결과: {result}")
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")

문제 2: finally를 사용하여 파일 닫기

📌 파일을 읽는 과정에서 예외가 발생해도, finally 블록에서 파일을 안전하게 닫도록 만드세요.

# 🔽 여기에 코드 작성
try:
    f = open("example.txt", "r")
    content = f.read()
    print(content)
except FileNotFoundError:
    print("파일을 찾을 수 없습니다.")
finally:
    if 'f' in locals():
        f.close()

문제 3: 사용자 정의 예외 클래스 생성

📌 음수를 입력하면 NegativeNumberError를 발생시키는 함수를 만드세요.

class NegativeNumberError(Exception):
    # 🔽 여기에 코드 작성
class NegativeNumberError(Exception):
    pass

def check_positive(num):
    if num < 0:
        raise NegativeNumberError("음수는 허용되지 않습니다.")

try:
    check_positive(-5)
except NegativeNumberError as e:
    print(e)  # 음수는 허용되지 않습니다.

문제 4: 로그 파일에 오류 메시지 기록하기

📌 오류가 발생할 경우 app.log 파일에 로그를 저장하도록 설정하세요.

import logging
# 🔽 여기에 코드 작성
import logging

logging.basicConfig(filename="app.log", level=logging.ERROR, format="%(asctime)s - %(levelname)s - %(message)s")

try:
    result = 10 / 0
except ZeroDivisionError as e:
    logging.error(f"예외 발생: {e}")

 

728x90