◎ 파이썬에서의 오류(error)
파이썬을 비롯한 프로그래밍 언어에서 오류는 크게 2가지로 나누어 볼 수 있다.
- 구문 오류(syntax error) : 프로그램 실행 전에 발생하는 오류
- 런타임 오류(runtime error) 또는 예외(exception) : 프로그램 실행 중에 발생하는 오류
1) 구문 오류
구문 오류란 문법적인 부분에서 발생하는 오류를 말한다. 괄호의 개수, 들여쓰기, 따옴표의 개수 불일치 등으로 인해 프로그램이 실행되기도 전에 발생하는 오류이다.
# 따옴표 개수 불일치
print("Hello)
2) 런타임 오류 or 예외
런타임 오류 또는 예외란 프로그램이 실행되는 도중에 발생하는 오류이다. 선언되지 않은 변수의 사용이나 리스트의 범위를 벗어난 인덱스에 접근하는 경우 등에 발생한다.
# 리스트 범위 초과 접근
num_list = [1, 2, 3, 4, 5]
for i in range(6):
print(num_list[i])
◎ 예외 처리(exception handling)
구문 오류가 아닌 예외(런타임 오류)를 처리하는 것을 예외 처리(exception handling)라고 한다. 참고로 구문 오류는 프로그램이 실행되기도 전에 발생하는 오류이므로 예외 처리 방법처럼 처리할 수는 없다. 예외 처리 방법에는 두 가지가 있다.
- 조건문(if)을 사용하는 방법
- try~except 구문을 사용하는 방법
1) 조건문(if)을 사용한 예외 처리
input_value = input()
# 입력한 값이 정수일 경우에만 가능
print(int(input_value))
위 코드는 입력받은 값을 정수형으로 출력하는 코드이다. 당연히 정수를 입력하면 문제가 발생하지 않지만 정수가 아닌 데이터를 입력하게 되면 예외가 발생한다. 위 경우에서는 ValueError가 발생하였다. 그렇다면 위 상황처럼 예외가 발생하는 경우를 고려하여 조건문으로 처리해보겠다.
input_value = input()
# 조건문을 사용한 예외 처리
if input_value.isdigit():
print(int(input_value))
else:
print("Not Integer Type Value")
이처럼 조건문을 사용하여 발생할 예외를 처리해주면 정수형이 아닌 데이터가 입력되었더라도 프로그램이 강제로 종료되지 않고 정상적으로 종료될 수 있게 된다.
2) try~except 구문을 사용한 예외 처리
try~except 구문은 조건문을 사용한 예외 처리보다 훨씬 더 사용하기 편리하다. 기본적인 구조는 아래와 같다.
try:
예외가 발생할 가능성이 있는 코드
except:
예외가 발생했을 때 실행할 코드
else:
예외가 발생하지 않았을 때 실행할 코드
finally:
예외 발생 여부에 관계없이 실행할 코드
try 구문은 절대 단독으로는 사용될 수 없고 반드시 except나 finally와 함께 사용되어야 한다. 사용 가능한 조합은 아래와 같다.
- try + except
- try + except + else
- try + except + finally
- try + except + else + finally
- try + finally
위 조합은 반드시 나열한 순서대로 사용해야 하며 만약 else가 except보다 앞에 오는 것처럼 순서가 바뀐다면 오류가 발생하게 된다. 위에서 다루었던 예외가 발생할 가능성이 있는 코드를 이번에는 try ~ except 구문을 사용하여 처리해보자.
input_value = input()
# try~except 구문을 사용한 예외 처리
try:
print(int(input_value))
except:
print("Not Integer Type Value")
조건문을 사용한 예외 처리와 동일하게 정수가 아닌 데이터를 입력한 경우에는 except 부분의 코드가 실행되는 것을 확인할 수 있다. 만약 오류가 발생해도 일단 별도의 처리는 하지 않되, 프로그램의 강제 종료를 막기 위해선 except 부분에 pass 키워드를 넣어주면 된다.
input_value = input()
# try~except 구문을 사용한 예외 처리
try:
print(int(input_value))
except:
pass
이번에는 else 구문도 함께 사용하여 예외 처리를 해보자. else 구문은 예외가 발생하지 않고 정상적으로 실행이 됐을 때 실행되는 코드이다.
input_value = input()
# try~except 구문을 사용한 예외 처리
try:
print(int(input_value))
except:
print("Not Integer Type Value")
else:
print("Integer Type Value")
else 구문을 추가함으로써 정수(123)가 입력되어 프로그램이 정상적으로 실행되었다는 것을 출력문을 통해 확인할 수 있게 되었다. 이제 마지막으로 finally 구문도 추가하여 예외 처리를 해보자.
input_value = input()
# try~except 구문을 사용한 예외 처리
try:
print(int(input_value))
except:
print("Not Integer Type Value")
else:
print("Integer Type Value")
finally:
print("Exit program")
finally 구문을 통해 예외가 발생하지 않고 정상적으로 실행이 된 경우와 예외가 발생한 경우에도 모두 실행될 공통적인 코드를 삽입할 수 있게 되었다.
2-1) try 구문 내부 return 키워드
try 구문 내부에 return 키워드가 있다면 바로 실행이 종료될까? 아래 코드를 통해 확인해보자.
def print_n(n):
try:
# 매개변수를 정수형으로 출력
print(int(n))
return
print("After return")
except:
print("예외 발생")
else:
print("정상 실행")
finally:
print("print_n() 종료")
print_n(3)
print()
print_n('abc')
print_n() 함수는 매개변수를 정수형으로 출력하는 코드로써 매개변수가 정수형이 아닌 경우에는 예외가 발생한다. 매개변수로 3이 전달된 경우에는 정상적으로 출력이 됐지만 return 이후의 코드는 실행이 되지 않는 것을 확인할 수 있다. 추가로 매개변수로 정수가 전달된 경우와 문자열이 전달된 경우 모두 finally 부분은 실행되는 것을 확인할 수 있다. 따라서 return 키워드를 만나더라도 finally 부분은 반드시 실행된다는 것을 알 수 있다.
2-2) try 구문 내부 break, continue
def fun():
for i in range(10):
try:
if i == 3:
continue
if i == 5:
break
except:
print("Run Except")
else:
print(i)
finally:
print("fun 함수 종료")
fun()
위 코드는 for 반복문 내부의 try 구문이 사용되었다. i가 3인 경우에는 건너뛰고(continue) i가 5인 경우에는 실행이 종료(break)된다. 출력 결과를 확인해보면 finally 부분의 코드는 continue, break가 된 경우에도 실행이 된다는 것을 확인할 수 있다.
3) 예외 종류별 처리
예외가 발생하는 원인은 정말 다양하고 또 그만큼 당연히 예외의 종류도 다양하다. 파이썬에서는 발생한 예외를 종류별로 처리하는 것이 가능하다.
input_value = input()
# try~except 구문을 사용한 예외 처리
try:
print(int(input_value))
except Exception as exception:
print("Not Integer Type Value")
print(type(exception))
print(exception)
위 코드는 try 구문을 사용하여 예외를 처리하고 있고 except 구문에서는 모든 예외(Exception)에 대한 처리를 하고 있다. 발생한 예외는 이를 저장할 변수(위 코드에서는 exception)에 저장하여 type과 내용을 출력할 수 있다. 위 코드에서 발생한 예외의 타입은 ValueError이므로 코드를 아래와 같이 수정할 수 있다.
input_value = input()
# try~except 구문을 사용한 예외 처리
try:
print(int(input_value))
except ValueError as exception:
print("Not Integer Type Value")
print(type(exception))
print(exception)
이번에는 리스트의 인덱스 범위를 초과한 접근을 시도했을 때 발생하는 예외를 처리해보자. 이때 발생하는 예외의 종류는 IndexError이므로 이에 맞게 수정해주면 된다.
value_list = [1, 2, 3, 4, 5]
# try~except 구문을 사용한 예외 처리
try:
print(value_list[5])
except IndexError as exception:
print("IndexError")
print(type(exception))
print(exception)
이로써 발생할 예외를 종류별로 처리할 수 있다는 것을 확인하였다. 그러면 이번에는 except 구문을 여러개 사용하여 하나의 코드에서 발생할 수 있는 예외를 종류별로 처리해보자.
value_list = [1, 2, 3, 4, 5]
# try~except 구문을 사용한 예외 처리
try:
n = int(input("> "))
print(value_list[n])
except IndexError as exception:
print("IndexError")
print(type(exception))
print(exception)
except ValueError as exception:
print("ValueError")
print(type(exception))
print(exception)
이처럼 except 구문을 여러개 사용하면 발생할 오류를 종류별로 처리할 수 있게 되므로 어느 상황에서 어떤 예외가 발생하는지 확인이 필요한 경우 등에 맞게 사용하면 예외를 처리하기 수월해진다.
'[Programming Language] > [Python]' 카테고리의 다른 글
[Python] :: 모듈, 패키지, 라이브러리, 프레임워크의 차이 / 모듈 세부 내용 (0) | 2023.07.14 |
---|---|
[Python] :: 데코레이터(decorator) - '@' (0) | 2023.07.10 |
[Python] :: 파일 처리(파일 입출력) - open(), close(), read(), write(), with 키워드 (0) | 2023.07.06 |
[Python] :: 튜플(tuple), 람다(lambda) (0) | 2023.07.05 |
[Python] :: 함수, 매개변수(가변 매개변수, 기본 매개변수, 키워드 매개변수), 함수 호출 형태, 리턴(return) (0) | 2023.07.04 |