예외 클래스와 예외 처리 (python)

Kyeongmin·2021년 9월 12일
0

Clean Code 책을 읽으며, 예외 처리의 중요성에 대해서 깨닫게 되고 그동안 마구잡이로 구현했던 예외 처리에 대해서 다시금 생각해보는 계기가 되었다.
이번 기회를 통해 python의 예외 클래스, 예외 처리 방법에 대해서 정리해보고자 한다.

이번 글은 단순히 python의 내장 예외 클래스와 예외 처리 구현 방법에 대해서 정리하고, 다음에는 예외 처리에 대한 개념을 집중적으로 공부하고 정리해보자.

1. 예외 처리 키워드

먼저 예외 처리에 사용되는 키워드에 대해서 살펴보자.

키워드설명
try메인 실행 코드, 오류를 탐지하는 구간
excepttry문에서 오류가 발생하는 경우 실행되는 구간
elsetry문에서 오류가 발생하지 않는 경우 실행되는 구간
finally오류 발생 여부와 상관 없이 실행되는 구간
raise사용자가 직접 오류를 발생시키는 경우

위와 같이 5개의 키워드로 이루어져 있고, try / except 절은 예외처리에서 필수적으로 사용되며, 나머지 구문은 필요에 의해 사용된다.

2. 예외 처리 사용하기

❓예외 처리는 왜 필요할까

먼저 우리가 여러개의 csv 파일을 불러오는 작업을 한다고 생각해보자.

def read_csv(file):
    csv = open(file, 'r')
    return csv

files = ['whereAmI.csv', 'visitor.csv', 'like.txt']
for file in files:
    csv = read_csv(file)
    
    if csv not None:
        print(csv.name)

여기서 whereAmI.csv 파일이 존재하지 않는다면,
아래와 같이 에러와 함께 프로그램이 중단되는 것을 확인할 수 있다.

FileNotFoundError: [Errno 2] No such file or directory: '12.abc'

이렇게 프로그램이 중단되는 경우를 사전에 방지하기 위해 예외 처리가 필요하다.

📌 try, except

앞서 말했듯이 try, except 절은 예외 처리문을 구현할때 필수적으로 사용하는 키워드이다.
try 절은 본래 실행시키고자 하는 부분이고, except 절은 오류가 발생했을 때 실행시키고자 하는 부분이다.

그럼 read_csv() 함수에 예외 처리 구문을 추가한 뒤 실행한다면,

def read_csv(file):
    try:
        csv = open(file, 'r')
        return csv
    except FileNotFoundError:
    	print("Can't Open {0}".format(file))
    except Exception as e:
        print("Error : {0}".format(e))
Can't Open whereAmI.csv
visitor.csv
like.txt

파일이 없는 경우 except 절이 실행되고 정상적으로 종료되는 것을 확인할 수 있다.

  • except 절은 위와 같이 여러번 사용할 수 있지만 먼저 작성된 순서대로 처리하기 때문에, 예외 처리 순서에 유의하며 작성해야 한다.
    예를 들어, 위의 except 절의 순서를 바꾼다면 파일을 찾을 수 없어 FileNotFoundError가 발생하더라도 Exception 구문이 실행된다.
  • except 절은 FileNotFoundError처럼 특정한 오류에 대해서 예외 처리를 할 수 있고, Exception의 경우 모든 오류에 대해서 예외 처리를 할 수 있다.

📌 else, finally

else, finally 절의 사용 방법은 read_csv() 함수의 문제점을 수정하며 알아가보자.
read_csv() 함수가 가지고 있는 문제는 사용한 자원을 반환하지 않는다는 것이다.

def read_csv(file):
    try:
        csv = open(file, 'r')
        return csv
    except FileNotFoundError:
    	print("Can't Open {0}".format(file))
    except Exception as e:
        print("Error : {0}".format(e))
    else: # 예외가 발생하지 않았을 때 실행하는 구문
        csv.close()
    finally: # 예외 발생 여부와 상관없이 실행하는 구문
        print('finish')

파일이나 네트워크 같은 자원 반환 작업은 예외 여부와 상관 없는 finally 절에 구현하는 것이 일반적이나, read_csv()의 경우 예외가 발생하지 않는 경우에만 open() 함수를 통해 자원을 사용하기 때문에 else 절에 구현했다.

📌 raise

read_csv 함수에 파일 확장자가 csv가 아닌 경우,
이를 필터링 하는 기능을 추가하면서 raise의 사용 방법을 익혀보자.

- 내장 예외 클래스

def read_csv(file):
    try:
        extension = file.split('.')[-1]
        if extension != "csv":
            raise Exception('파일 확장자를 확인해주세요.')
            
        csv = open(file, 'r')
        return csv
    except FileNotFoundError:
    	print("Can't Open {0}".format(file))
    except Exception as e:
        print("Error : {0}".format(e))
Can't Open whereAmI.csv
visitor.csv
Error : 파일 확장자를 확인해주세요.

- 사용자 정의 예외

# class 예외명(Exception):
class FileExtensionError(Exception):
    def __init__(self):
    	#super().__init__(예외 메세지)
        super().__init__('파일 확장자를 확인해주세요.')

def read_csv(file):
    try:
        extension = file.split('.')[-1]
        if extension != "csv":
            raise FileExtensionError
            
        csv = open(file, 'r')
        return csv
    except FileNotFoundError:
    	print("Can't Open {0}".format(file))
    except Exception as e:
        print("Error : {0}".format(e))
Can't Open whereAmI.csv
visitor.csv
Error : 파일 확장자를 확인해주세요.

- 예외 재호출

현재 발생했던 예외를 다시 발생시킬 수 있는데, 방법은 아래와 같다.

def divideZero(num1):
    try:
        result = num1 / 0
        return result
    except ZeroDivisionError:
        raise

try:
    divideZero(3)
except Exception as e:
    print("Error : {0}".format(e))
Error : division by zero

3. 내장 예외 클래스

🔗 Python Built-in Exceptions
python 내장 예외 클래스를 한번 읽어보는 것도 큰 도움이 될 것 같다.

profile
개발자가 되고 싶은 공장장이🛠

0개의 댓글