Clean Code 책을 읽으며, 예외 처리의 중요성에 대해서 깨닫게 되고 그동안 마구잡이로 구현했던 예외 처리에 대해서 다시금 생각해보는 계기가 되었다.
이번 기회를 통해 python의 예외 클래스, 예외 처리 방법에 대해서 정리해보고자 한다.
이번 글은 단순히 python의 내장 예외 클래스와 예외 처리 구현 방법에 대해서 정리하고, 다음에는 예외 처리에 대한 개념을 집중적으로 공부하고 정리해보자.
먼저 예외 처리에 사용되는 키워드에 대해서 살펴보자.
키워드 | 설명 |
---|---|
try | 메인 실행 코드, 오류를 탐지하는 구간 |
except | try문에서 오류가 발생하는 경우 실행되는 구간 |
else | try문에서 오류가 발생하지 않는 경우 실행되는 구간 |
finally | 오류 발생 여부와 상관 없이 실행되는 구간 |
raise | 사용자가 직접 오류를 발생시키는 경우 |
위와 같이 5개의 키워드로 이루어져 있고, try / except 절은 예외처리에서 필수적으로 사용되며, 나머지 구문은 필요에 의해 사용된다.
먼저 우리가 여러개의 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
절은 오류가 발생했을 때 실행시키고자 하는 부분이다.
그럼 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
절의 사용 방법은 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
절에 구현했다.
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
🔗 Python Built-in Exceptions
python 내장 예외 클래스를 한번 읽어보는 것도 큰 도움이 될 것 같다.