[Python] 예외 처리

DU·2024년 7월 25일
0

Python

목록 보기
4/8
post-thumbnail

Python의 예외처리는 코드 실행 중 발생할 수 있는 오류를 관리하고 처리하는 데 중요한 역할을 합니다. 예외처리를 잘 이해하면 프로그램의 안정성을 높이고, 예기치 않은 상황에서도 프로그램이 올바르게 작동하도록 할 수 있습니다. 이 글에서는 Python의 예외처리에 대한 기초부터 고급 활용까지 자세히 설명하겠습니다.

Python 예외처리

1. 예외처리란 무엇인가?

예외처리는 프로그램 실행 중 발생할 수 있는 오류나 예외 상황을 처리하는 방법입니다. Python에서는 예외가 발생하면 프로그램의 기본 흐름이 중단되고, 예외가 발생한 위치에서 예외가 발생했음을 알리는 메시지를 출력합니다.

2. 기본 예외처리 구문

try-except 블록

try-except 블록을 사용하여 예외를 처리할 수 있습니다. try 블록에는 예외가 발생할 가능성이 있는 코드를 작성하고, except 블록에는 예외 발생 시 실행할 코드를 작성합니다.

try:
    # 예외가 발생할 가능성이 있는 코드
    result = 10 / 0
except ZeroDivisionError:
    # 예외가 발생했을 때 실행할 코드
    print("0으로 나눌 수 없습니다.")

출력:

0으로 나눌 수 없습니다.

3. 여러 예외 처리

여러 예외를 처리하는 방법

except 블록을 여러 개 사용하여 다양한 예외를 처리할 수 있습니다.

try:
    result = 10 / 0
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
except ValueError:
    print("값 오류가 발생했습니다.")

모든 예외 처리

모든 예외를 포괄적으로 처리하려면 Exception 클래스를 사용합니다.

try:
    result = 10 / 0
except Exception as e:
    print(f"예외가 발생했습니다: {e}")

출력:

예외가 발생했습니다: division by zero

4. 예외 발생시키기

raise 키워드

raise 키워드를 사용하여 예외를 발생시킬 수 있습니다. 이는 사용자 정의 조건에서 예외를 발생시키는 데 유용합니다.

def check_value(value):
    if value < 0:
        raise ValueError("값은 0보다 커야 합니다.")
    return value

try:
    check_value(-1)
except ValueError as e:
    print(e)

출력:

값은 0보다 커야 합니다.

예외 체인

raise 키워드를 사용하여 예외를 다시 발생시킬 수 있습니다. 이를 통해 기존 예외 정보를 유지하면서 새로운 예외를 발생시킬 수 있습니다.

try:
    try:
        result = 10 / 0
    except ZeroDivisionError as e:
        raise ValueError("값 오류가 발생했습니다.") from e
except ValueError as e:
    print(f"새로운 예외: {e}")
    print(f"원래 예외: {e.__cause__}")

출력:

새로운 예외: 값 오류가 발생했습니다.
원래 예외: division by zero

5. 예외 처리 고급 기능

else 블록

try 블록에서 예외가 발생하지 않은 경우 실행할 코드를 else 블록에 작성합니다.

try:
    result = 10 / 2
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
else:
    print(f"결과는 {result}입니다.")

출력:

결과는 5.0입니다.

finally 블록

finally 블록은 예외 발생 여부에 관계없이 항상 실행되는 코드를 작성합니다. 자원 정리 및 해제에 유용합니다.

try:
    result = 10 / 0
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
finally:
    print("예외 처리 완료.")

출력:

0으로 나눌 수 없습니다.
예외 처리 완료.

finally 블록 사용 예제

finally 블록은 파일이나 네트워크 연결과 같은 자원을 정리할 때 유용합니다.

try:
    file = open("example.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("파일을 찾을 수 없습니다.")
finally:
    file.close()
    print("파일을 닫았습니다.")

출력:

파일을 찾을 수 없습니다.
파일을 닫았습니다.

6. with 문과 컨텍스트 매니저

with 문은 자원을 할당하고 해제하는 과정을 자동으로 처리합니다. 파일 작업에서 자주 사용됩니다.

try:
    with open('non_existent_file.txt', 'r') as file:
        content = file.read()
except FileNotFoundError:
    print("파일을 찾을 수 없습니다.")

출력:

파일을 찾을 수 없습니다.

with 문 사용 예제

with 문을 사용하면 파일을 열고 닫는 과정을 자동으로 처리할 수 있어 코드가 더 간결해집니다.

try:
    with open("example.txt", "r") as file:
        content = file.read()
        print(content)
except FileNotFoundError:
    print("파일을 찾을 수 없습니다.")

출력:

(파일 내용 출력 혹은 파일이 없을 때 "파일을 찾을 수 없습니다.")

사용자 정의 컨텍스트 매니저

with 문을 사용하려면 객체가 __enter____exit__ 메서드를 구현해야 합니다. 이를 통해 사용자 정의 컨텍스트 매니저를 만들 수 있습니다.

class CustomContext:
    def __enter__(self):
        print("리소스를 획득합니다.")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("리소스를 해제합니다.")

with CustomContext() as context:
    print("리소스를 사용하는 중입니다.")

출력:

리소스를 획득합니다.
리소스를 사용하는 중입니다.
리소스를 해제합니다.

7. 사용자 정의 예외

사용자 정의 예외 클래스

기본 제공 예외 클래스 외에 사용자 정의 예외 클래스를 정의할 수 있습니다.

class CustomError(Exception):
    pass

def check_value(value):
    if value < 0:
        raise CustomError("값은 0보다 커야 합니다.")
    return value

try:
    check_value(-1)
except CustomError as e:
    print(e)

출력:

값은 0보다 커야 합니다.

8. Python과 Java의 예외처리 비교

Python의 예외처리

  • 예외를 try-except 블록으로 처리
  • 모든 예외는 Exception 클래스를 상속받아 처리
  • elsefinally 블록을 사용하여 추가적인 예외 처리 가능

Java의 예외처리

  • 예외를 try-catch 블록으로 처리
  • 모든 예외는 Throwable 클래스를 상속받아 처리
  • finally 블록을 사용하여 자원 해제 가능
  • 체크 예외와 언체크 예외로 구분

Java 예제:

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("0으로 나눌 수 없습니다.");
} finally {
    System.out.println("예외 처리 완료.");
}

출력:

0으로 나눌 수 없습니다.
예외 처리 완료.

9. 예외처리의 장단점

장점

  1. 명확한 오류 처리: 예외 발생 시 명확한 오류 메시지를 제공하여 문제를 쉽게 파악할 수 있습니다.
  2. 프로그램 안정성 향상: 예외처리를 통해 프로그램이 예기치 않게 종료되지 않도록 할 수 있습니다.
  3. 자원 관리 용이: finally 블록이나 with 문을 사용하여 자원 해제를 자동으로 처리할 수 있습니다.

단점

  1. 복잡성 증가: 여러 예외를 처리하다 보면 코드가 복잡해질 수 있습니다.
  2. 퍼포먼스 저하: 과도한 예외처리는 프로그램의 성능을 저하시킬 수 있습니다.
  3. 오류 은폐 가능성: 예외를 지나치게 포괄적으로 처리하면, 실제 오류를 발견하고 수정하는 데 어려움이 있을 수 있습니다.

10. 추가 예제와 유용한 팁

데이터베이스 연결 예제

데이터베이스 연결과 같은 자원 관리는 예외처리를 통해 안정적으로 처리할 수 있습니다.

import sqlite3

def connect_to_db(db_name):
    try:
        conn = sqlite3.connect(db_name)
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM non_existent_table")
    except sqlite3.DatabaseError as

 e:
        print(f"데이터베이스 오류: {e}")
    finally:
        if conn:
            conn.close()

# 사용 예시
connect_to_db('example.db')

출력:

데이터베이스 오류: no such table: non_existent_table

예외 처리 팁

  • 구체적인 예외 처리: 가능한 구체적인 예외를 처리하여 문제를 정확히 파악합니다.
  • 로그 기록: 예외 발생 시 로그를 남겨 문제를 추적하고 해결할 수 있습니다.
  • 적절한 예외 전환: 특정 예외를 다른 예외로 전환하여 호출자에게 유용한 정보를 제공합니다.

Python의 예외처리는 프로그램의 안정성과 유지보수성을 높이는 데 중요한 역할을 합니다. 기초적인 try-except 구문부터 고급 기능인 else, finally, 사용자 정의 예외까지 다양한 예외처리 방법을 이해하고 활용하면 더 견고하고 안정적인 코드를 작성할 수 있습니다.

0개의 댓글