개발 같이해요/PYTHON

[ python ] 실무예제로 배우는 파이썬 예외 처리 방법

Rio - Moon 2024. 9. 3. 11:08
728x90
반응형

 

 

 

프로그래밍을 하다 보면 예상치 못한 오류나 예외 상황을 마주할 때가 많습니다. 이러한 오류를 적절히 처리하지 않으면 프로그램이 갑작스럽게 중단되거나, 원하지 않는 동작을 할 수 있습니다. 파이썬은 이런 상황을 관리하기 위해 강력한 예외 처리 메커니즘을 제공합니다. 이번 포스팅에서는 파이썬의 예외 처리 방법에 대해 실무 예제를 통해 자세히 알아보겠습니다

 

 

그 외에 파이썬의 연사자 와 함수 에 대해 궁금하시면 아래 포스팅을 같이 참고해주세요

 


 

 

# 1. 파이썬 예외 처리의 기본 개념

 

예외(Exception)란 무엇인가?

예외는 프로그램 실행 중에 발생하는 예상치 못한 상황이나 오류를 말합니다. 예를 들어, 숫자를 0으로 나누려고 하거나, 존재하지 않는 파일을 열려고 할 때 발생하는 오류가 바로 예외입니다. 이러한 예외가 발생하면 프로그램은 기본적으로 즉시 중단되지만, 예외 처리를 통해 프로그램이 중단되지 않고 안정적으로 실행될 수 있도록 할 수 있습니다.

프로그램 실행 중 발생할 수 있는 다양한 오류 유형

파이썬에서는 ZeroDivisionError, ValueError, FileNotFoundError 등 다양한 내장 예외 유형을 제공합니다. 각 예외는 특정한 오류 상황에 대해 정의되어 있으며, 이러한 예외들을 적절히 처리하는 것이 중요합니다.

 

 

 

# 2.try-except 구조

 

try-except 구조는 파이썬에서 가장 기본적인 예외 처리 방법입니다. try 블록 안에는 예외가 발생할 수 있는 코드를 작성하고, except 블록에서는 예외가 발생했을 때 실행할 코드를 작성합니다.

 

 

 

try-except 구조 예시

 

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

 

위 코드에서 0으로 나누기를 시도하면 ZeroDivisionError 예외가 발생하고, 프로그램은 중단되지 않고 except 블록이 실행됩니다.

 

그렇다면 실무에서는 어떤 식으로 쓰이는지 같이 살펴보도록 하겠습니다.

 

실무 예제 1: 사용자 입력 처리

 

🚩 사용자 입력 처리   🚩

try:
    num = int(input("숫자를 입력하세요: "))
    result = 100 / num
    print(f"결과: {result}")
except ValueError:
    print("유효한 숫자를 입력하세요.")
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")

 

위 코드에서 ValueError와 ZeroDivisionError를 각각 처리하여, 사용자가 잘못된 입력을 했을 때도 프로그램이 종료되지 않고 안내 메시지를 출력하도록 합니다.

 

실무 예제 2: 파일 읽기

🚩 파일 읽기  🚩

 

파일을 읽는 작업은 파일이 존재하지 않거나 접근 권한이 없는 경우 예외가 발생할 수 있습니다. 이를 try-except 구조로 처리해보겠습니다.

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

 

 

위 코드에서는 FileNotFoundError 예외가 발생할 때 사용자에게 파일이 존재하지 않음을 알려줍니다.

 

 

# 3.다양한 예외 처리 방법

 

여러 예외를 처리하는 방법

실무에서는 여러 종류의 예외를 처리해야 하는 상황이 자주 발생합니다. 이를 위해 각 예외에 대해 개별적으로 except 블록을 작성하거나, 포괄적으로 처리할 수 있습니다.

 

실무 예제: 데이터베이스 연결 및 쿼리 실행

 

🚩 데이터베이스 연결 및 쿼리 실행 🚩

 

데이터베이스와의 연결 작업은 네트워크 상태나 데이터베이스 서버의 상태에 따라 다양한 예외가 발생할 수 있습니다.

try:
    connection = db.connect("database_url")
    result = connection.execute("SELECT * FROM users")
except ConnectionError:
    print("데이터베이스에 연결할 수 없습니다.")
except TimeoutError:
    print("쿼리 실행 시간이 초과되었습니다.")
except OperationalError as e:
    print(f"데이터베이스 작업 중 오류가 발생했습니다: {e}")

 

여기서는 ConnectionError, TimeoutError, OperationalError 등을 개별적으로 처리하여, 각각의 상황에 맞는 에러 메시지를 출력합니다.

 

모든 예외를 포괄하는 방법

때로는 발생할 수 있는 모든 예외를 포괄적으로 처리해야 할 때가 있습니다. 이때는 except Exception as e를 사용하여 모든 예외를 한 번에 처리할 수 있습니다.

 

실무 예제: 외부 API 호출

 

🚩 외부 API 호출 🚩

 

외부 API를 호출하는 작업에서 다양한 예외가 발생할 수 있습니다. 예를 들어 네트워크 문제, 서버 오류 등이 있을 수 있습니다.

try:
    response = requests.get("https://api.example.com/data")
    data = response.json()
except Exception as e:
    print(f"API 호출 중 오류가 발생했습니다: {e}")

 

이 코드에서는 모든 예외를 포괄하여 처리하되, 발생한 예외 메시지를 출력하여 문제를 파악할 수 있도록 합니다.

 

 

# 4. else와 finally 블록 사용

 

try-except 구조에 else와 finally 블록을 추가하면 예외 처리의 유연성을 높일 수 있습니다.

else 블록

else 블록은 try 블록에서 예외가 발생하지 않았을 때 실행됩니다. 예외가 발생하지 않은 경우에만 특정 작업을 수행하고 싶을 때 유용합니다.

 

 

실무예시 : 파일 처리 후 데이터 파싱

 

🚩 파일 처리 후 데이터 파싱  🚩

 

파일을 성공적으로 읽은 후, 데이터를 파싱하는 작업을 else 블록에서 수행할 수 있습니다.

 

try:
    with open('data.txt', 'r') as file:
        content = file.read()
except FileNotFoundError:
    print("파일을 찾을 수 없습니다.")
else:
    parsed_data = parse_data(content)
    print("데이터 파싱이 성공적으로 완료되었습니다.")

 

이 코드는 파일을 읽는 데 문제가 없을 경우에만 데이터를 파싱하는 로직을 수행합니다.

 

 

finally 블록

finally 블록은 예외 발생 여부와 관계없이 항상 실행되는 코드를 작성할 때 사용합니다. 자원 해제나 정리 작업 등에 주로 사용됩니다.

 

실무 예제: 데이터베이스 연결 종료

 

 

🚩데이터베이스 연결 종료  🚩

 

데이터베이스 연결을 종료할 때 finally 블록을 사용하여 항상 연결을 종료하도록 할 수 있습니다.

 

try:
    connection = db.connect("database_url")
    result = connection.execute("SELECT * FROM users")
except Exception as e:
    print(f"오류가 발생했습니다: {e}")
finally:
    connection.close()
    print("데이터베이스 연결이 종료되었습니다.")

 

이 코드에서는 예외가 발생하더라도 항상 finally 블록에서 데이터베이스 연결을 종료하도록 합니다.

 

 

 

# 5. 사용자 정의 예외 처리

 

사용자 정의 예외 클래스 만들기

 

특정한 상황에서 발생하는 사용자 정의 예외를 만들어서, 더 의미 있는 예외 처리를 할 수 있습니다.

 

 

실무 예제

 

 

🚩데이터베이스 연결 종료  🚩

 

나이를 입력받아 특정 조건에서 예외를 발생시키는 사용자 정의 예외를 만들어보겠습니다.

class InvalidAgeError(Exception):
    def __init__(self, age, message="유효하지 않은 나이입니다."):
        self.age = age
        self.message = message
        super().__init__(self.message)

def check_age(age):
    if age < 0:
        raise InvalidAgeError(age)
    elif age < 18:
        print("미성년자입니다.")
    else:
        print("성인입니다.")

try:
    check_age(-5)
except InvalidAgeError as e:
    print(f"오류: {e.age}는 {e.message}")

 

이 예제에서는 음수의 나이를 입력하면 InvalidAgeError를 발생시키고, 예외를 처리하여 사용자에게 유효하지 않은 나이임을 알립니다.

 

 

# 5. 예외 처리 모범사례

예외 처리를 잘못하면 코드의 가독성이 떨어지고, 유지 보수가 어려워질 수 있습니다.

다음은 예외 처리 시 고려해야 할 베스트 프랙티스( 모범사례 ) 입니다.

 

  • 예외 남용 방지
    • 예외는 프로그램의 흐름을 제어하는 수단으로 남용하지 않아야 합니다. 예외는 진짜 예외 상황에서만 사용하고, 일반적인 조건문으로 처리할 수 있는 상황에서는 예외를 사용하지 않는 것이 좋습니다.
  • 적절한 에러 메시지 작성하기
    • 에러 메시지는 명확하고 구체적이어야 합니다. 사용자가 문제를 이해하고 해결할 수 있도록 도움이 되는 정보를 제공하는 것이 중요합니다.
  • 로깅(logging)과 예외 처리의 관계
    • 로깅을 활용하여 예외 발생 시 기록을 남기면, 문제를 파악하고 추적하는 데 도움이 됩니다. 특히, 실무 환경에서는 로깅을 통해 예외 발생 원인을 신속히 파악할 수 있습니다.

 

실무 예제: 로깅을 활용한 예외 처리

 

 

🚩 로깅을 활용한 예외 처리   🚩

 

 

import logging

logging.basicConfig(filename='app.log', level=logging.ERROR)

try:
    x = 1 / 0
except ZeroDivisionError as e:
    logging.error("0으로 나눌 수 없습니다.", exc_info=True)
    print("오류가 발생했습니다. 로그를 확인하세요.")

 

이 코드는 예외가 발생할 때 로그 파일에 오류 정보를 기록하고, 사용자에게 로그를 확인하도록 안내합니다.

 

 

# 5. 마무리

 

이번 포스팅에서는 파이썬에서 예외를 처리하는 다양한 방법과 실무에서 유용한 예제들을 살펴보았습니다. 예외 처리는 코드의 안정성과 신뢰성을 높이는 중요한 기술이며, 적절히 활용하면 예기치 않은 상황에서도 프로그램이 중단되지 않고 정상적으로 동작할 수 있습니다. 이 글을 통해 배운 예외 처리 기법을 실무에 적용해 보세요. 

 

반응형