본문 바로가기
프로그래밍 언어/파이썬

10.예외처리

by Jinger 2023. 3. 13.

서론

    어떠한 목적을 가지고 프로그램을 만들 경우 사용자가 정말 무슨 입력을 할지 행동을 할지 모두 예측하는 것은 불가능하다. 그렇기에 코딩을 할 때 예외 사항이 무엇이 있는지 생각해야 하며, 예외가 발생할 수 있는 구문이 생긴다면 아래와 같은 예외처리가 필요하다.


오류

   오류에는 두가지 종류가 있다. 구문 오류와 런타임 오류, 구문 오류는 프로그램 실행하기 이전에 발생(실행이 안 되는 오류)하며 주로 문법적인 오류를 말한다. 런타임 오류는 프로그램 실행 중에 발생하는 오류로 예외라고도 불린다.

# 예외로 발생한 오류는 디버그에 “exception :”로 나타남


조건문으로 예외

    조건문으로도 예외를 처리할 수 있다. 하지만 이 방법은 예외가 발생할 모든 상황을 예측하고 모두 조건문으로 처리해야 하므로 처리하기 힘들다. 아래 예시를 들자면, 정수를 입력하라고 설명이 되어 있지만, 사람들이 숫자를 정수로 넣을지 실수로 넣을지 심지어 영어나 한글로 넣을지 아무도 모른다.

num = int(input("정수를 입력하세요"))      #예외가 생길 만한 코드
if num.isdigit():                     #isdigit()는 숫자로만 구성되어 있는 자 확인하는 함수이다.
  print("원의 둘레: ", 2 * 3.14 * num)
else:
  print("정수가 입력되지 않았어요")

예외처리

    위 같은 코드는 프로그래머가 모든 상황을 예측할 수 없으므로 아래와 같은 키워드를 이용하여 예외상황을 대비한다.

try :
   #예외가 발생할 가능성이 있는 코드
except:
   #예외가 발생 했을 때 실행할 코드
else:
   #예외가 발생하지 않았을 때 실행할 코드
finally:
   #무조건 실행할 코드

 

    예외처리하기 위해 위의 키워드를 굳이 모두 사용할 필요가 없다. 아래와 같은 형식으로 사용이된다. 주의해야할 점으로는 try 구문은 단독으로 사용할 수 없으며, 반드시 except 혹은 finally와 함께 사용해야한다. else 구문은 반드시 except 구문 뒤에 사용해야한다.
try + except
try + except + else
try + except + finally
try + except + else + finally
try + finally
try:
   num = int(input("정수를 입력하세요"))
except:
   print("정수가 입력되지 않았어요")
else:
   print("원의 둘레: ", 2 * 3.14 * num)
finally:
   print("오류없이 완료하였습니다.")

예외 객체

   예외에는 많은 종류가 있고 클래스로 존재하기에 상속을 받거나 주기도 한다. 아래 더보기에 예외 클래스를 확인할 수 있고 각각 어떠한 의미를 가진 예외들이다.

더보기

BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
    +-- StopIteration
    +-- StopAsyncIteration
    +-- ArithmeticError
    |    +-- FloatingPointError
    |    +-- OverflowError
    |    +-- ZeroDivisionError
   +-- AssertionError
   +-- AttributeError
   +-- BufferError
   +-- EOFError
   +-- ImportError
   |    +-- ModuleNotFoundError
   +-- LookupError
   |    +-- IndexError
   |    +-- KeyError
   +-- MemoryError
   +-- NameError
   |    +-- UnboundLocalError
   +-- OSError
   |    +-- BlockingIOError
   |    +-- ChildProcessError
   |    +-- ConnectionError
   |    |    +-- BrokenPipeError
   |    |    +-- ConnectionAbortedError
   |    |    +-- ConnectionRefusedError
   |    |    +-- ConnectionResetError
   |    +-- FileExistsError
   |    +-- FileNotFoundError
   |    +-- InterruptedError
   |    +-- IsADirectoryError
   |    +-- NotADirectoryError
   |    +-- PermissionError
   |    +-- ProcessLookupError
   |    +-- TimeoutError
   +-- ReferenceError
   +-- RuntimeError
   |    +-- NotImplementedError
   |    +-- RecursionError
   +-- SyntaxError
   |     +-- IndentationError
   |     +-- TabError
   +-- SystemError
   +-- TypeError
   +-- ValueError
   |    +-- UnicodeError
   |    +-- UnicodeDecodeError
   |    +-- UnicodeEncodeError
   |    +-- UnicodeTranslateError
   +-- Warning
      +-- DeprecationWarning
      +-- PendingDeprecationWarning
      +-- RuntimeWarning
      +-- SyntaxWarning
      +-- UserWarning
      +-- FutureWarning
      +-- ImportWarning
      +-- UnicodeWarning
      +-- BytesWarning
      +-- ResourceWarning

 어떠한 예외가 발생하는지 직접 지정하여 사용할 수 있다.

try:
   #예외가 발생할 가능성이 있는 구문
except 예외의 종류 as 예외 객체를 활용할 변수 이름:
   #예외가 발생했을 때 실행할 구문

   위 예시를 활용하자면 아래와 같은 코드가 나온다.

try:
   num=int(input("정수 입력하세요"))
except ValueError:  #데이터 값 오류
   print("정수를 입력해 주세요")
else:
   print("원의 둘레: ", 2 * 3.14 * num)

모든 예외 잡기

    위 코드 또한 모든 예외를 잡은 것이 아니다. 모든 예외를 모두 예측하는 것은 힘들기에 상위 예외 클래스로 다른 예외에 대한 대비를 할 수 있다.

list_num=[32,158,74,12,0]
try:
  num=int(input(“정수 입력 :”))
  print(“{}번째 요소 : {}”.format(num, list_num[num])))

except ValueError:  #데이터 값 오류
  print(“정수를 입력해 주세요”)

except IndexError:  #잘못된 인덱스로 인덱싱할 때
  print(“리스트의 인덱스를 벗어났어요”)

except Exception as exception:   #위와 다른 예외 모두 잡기
  print(“미리 파악하지 못한 예외 발생”)
  print(type(exception),exception)  #무슨 예외인지 확인하는 코드

예외 강제 발생

   개발하는 동안 ‘이 부분을 그냥 넘어가면 나중에 큰 문제가 발생하니까 여기에서 강제 종료 시키자’라는 경우 혹은 예외 발생 시 처리를 확인하는 경우도 있다. 이때 강제로 예외를 발생시키기도 하는 데 raise키워드를 사용한다. "raise 예외 객체"형태로 예외를 강제 발생한다.

num=int("정수 입력: ") 
print("원의 둘레: ", 2 * 3.14 * num)

if num>0:
  raise NotImplementedError

else:
  raise NotImplementedError

예외 만들기

    때때로 내장에 내가 예상되는 상황이 없을 수 있다. 이럴 경우 직접 예외 클래스를 만들기도 한다. 

class 예외 이름(Exception):  #exception을 상속받아 클래스 생성
  def __init__(self):
  super().__init__('에러메세지')
class NotThreeMultipleError(Exception):
def __int__(self):
  super().__init__('3의 배수가 아닙니다.')

try:
  x=int(input('3의 배수를 입력하세요:'))
  if x%3!=0:
  raise NotThreeMultipleError
  print(x)

except Exception as e
  print('예외가 발생했습니다', e)

주섬주섬

   프로그램 작성 할 때 항상 예외적인 상황까지 모두 생각하는 습관을 기르는 게 중요하다. 또한, 너무 많은 상황을 모두 예측할 수 없지만, 최대한 잡을 수 있는 것들을 예측해 보고 잡을 수 있도록 노력하자.

참고

- 파이썬 공식 문서

 

반응형

'프로그래밍 언어 > 파이썬' 카테고리의 다른 글

12.기타  (1) 2023.03.20
11.파일  (0) 2023.03.13
9.클래스  (0) 2023.03.07
8.모듈  (0) 2023.03.02
7.함수  (0) 2023.02.27

댓글