이번 포스트에서는 파이썬에서 코드에서 에러가 발생했을 때, 강제적으로 프로세스를 종료되지 않고 코드 내부에서 에러를 핸들링하는 문법을 알아보고자 합니다.
에러를 코드내에서 처리해야하는 경우는 많은 경우가 있지만 대략 아래와 같을 겁니다.
- 디스크 쓰기 및 읽기도중 하드웨어에서 오류가 발생했거나 소켓등 통신관련 코드의 오류 확인 및 처리가 필요한 경우
- 쿼리문 문법의 한계등으로 파이썬 수준에서 에러 핸들링이 필요한 경우
- 기타 여러 소프트웨어나 하드웨어에서 오류가 발생했지만 프로세스 전체가 종료되기를 원치 않고 특정 코드에 대해서만 오류를 처리하고 싶은 경우
- 디버깅이 일시적으로 필요한 경우
- 기타 여러 경우
파이썬 코드 내에서 에러를 핸들링하는 기본적인 문법은 아래와 같습니다.
try:
print("[try")
에러발생=[True,False]
print("*"*3,("에러가 발생하는 경우" if(sum(에러발생)>0) else "에러가 발생하지 않는 경우"),"*"*3)
if(에러발생[0]==True):
raise Exception("가상 에러") from IOError #Exception이라는 에러를 강제적으로 발생시키는 코드, 이 줄 코드에서 IOError는 Exception("가상 에러")가 발생하는 본질적인 원인이라고 문법적으로 명시
#만약 문법이 raise None from IOError 이면, 발생된 에러를 IOError로 인식
"""
즉,raise <에러 클래스1> from <에러 클래스2> 이라면 <에러 클래스1>라고 인식하기에 큰 문제가 없으면 <에러 클래스1>로 1순위로 인식, <에러 클래스1>에 문제가 있으면 <에러 클래스2>를 2순위로 인식함
이때, 'from <에러 클래스2>'는 문법적으로 생략가능
즉, 'raise <에러 클래스1>' 만으로도 에러발생이 가능
"""
if(에러발생[1]==True):
raise StopIteration()#StopIteration이라는 에러를 강제적으로 발생시키는 코드
except StopIteration:
#try문 전체 코드가 완료되기 전까지 StopIteration이라는 에러가 발생하면 아래 문을 실행
print("StopIteration?")
except IOError as ioE:#IOError이라는 에러 변수에 접근할 수 있는 별칭을 함께 명시('ioE = getIOError()' 와 비슷)
#try문 전체 코드가 완료되기 전까지 IOError이라는 에러가 발생하면 아래 문을 실행
print("IOError?",ioE)
except Exception:#as exception
#try문 전체 코드가 완료되기 전까지 Exception 혹은 Exception을 상속하는 에러가 발생하면 아래 문을 실행
print("Exception?")
else:
#try문 전체 코드가 완료되기 전까지 파이썬에서 핸들링할 수 있는 어떤 에러도 발생하지 않았다면, try문 코드가 완료 된후 실행
print("else?")
finally:
#try문에서 에러가 발생여부에 상관없이 try문에 관련된 코드들이 모두 실행이 완료되면 아래 문을 실행
print("finally?")
print("]")



위의 결과로 보아 에러가 발생하면 해당 에러에 맞는 구문을 찾아가 실행하고 에러가 발생하지 않으면 else구문을 실행하는 것을 알 수 있었습니다.
이때 에러발생[1]=True로 변경하고, except Exception:#as exception 구문과 except StopIteration: 구문의 위치를 바꾸어 보면 어떻게 될까요?
즉,
try:
...
에러발생=[False,True]
...
except Exception:#as exception
#try문 전체 코드가 완료되기 전까지 Exception 혹은 Exception을 상속하는 에러가 발생하면 아래 문을 실행
print("Exception?")
except StopIteration:
#try문 전체 코드가 완료되기 전까지 StopIteration이라는 에러가 발생하면 아래 문을 실행
print("StopIteration?")
...
의 형식으로 코드를 일부 변경하게 되면,

StopIteration에 대한 구문을 처리하지 않고 Exception에 관한 구문을 처리한 것을 알 수 있습니다.
이것으로 같은 except 구문이라면 절차적으로 첫번째 구문부터 확인하고 순차적으로 마지막 구문까지 확인한다는 것을 알 수가 있습니다.
그런데 여기서 순차적으로 확인한다고 해도 왜 stopiteration 오류처리 구문이 아니라 exception 관련 구문으로 처리가 되었을까요?
그이유는 바로 stopiteration클래스가 exception 클래스를 상속하고 있기 때문입니다.(클래스 상속(class inheritance)에 대한 추가적인 내용은 클래스와 관련되었으니 이 포스트에서는 생략하겠습니다.)
파이썬에서는 해당 클래스가 어떤 클래스에 대해 상속했는지에 대한 여부를 알려주는 함수가 기본적으로 구현되어 있습니다.
바로 issubclass(클래스_상속되었다고_추측되는_클래스명,클래스_상속_여부_의_기준_클래스명)->bool 입니다.
issubclass는 쉽게 설명하면 기능적으로 두 클래스간의 클래스 상속의 관계가 성립하냐를 반환해주는 함수라고 할 수 있겠습니다.
다시 본론으로 돌아와 StopIteration클래스와 Exception의 클래스상속관계를 확인해보겠습니다.

이것으로 보아 Exception는 StopIteration을 클래스 상속하지 않았지만 StopIteration은 Exception을 클래스 상속한 것을 알 수 있습니다.
따라서 '순차적으로 exception관련 구문이 다른 에러처리 구문보다 위쪽에 있으면, exception을 상속한 에러처리관련 구문은 exception 구문이 우선적으로 처리된다' ,
즉, 'except문에서 클래스 상속관계의 부모 그 이상에 해당하는 클래스관련 구문이 순차적으로 먼저 있으면 그것을 우선한다'는 것을 알 수 있었습니다.
'Program Languages > Python' 카테고리의 다른 글
파이썬에서 심플한 웹서버 작동시키기 (2) | 2023.01.06 |
---|---|
파이썬 비트 연산자 사용법 (0) | 2023.01.06 |
파이썬 반복문 사용법(for, while) (0) | 2022.12.29 |
파이썬 콘솔 상호작용으로 입력받는 법 (0) | 2022.12.27 |
파이썬 print 함수로 문자 출력하기 (4) | 2022.12.23 |