Python - 예외처리

Python - 예외처리 try , except, raise

:: python tutorial :: Errors and Exceptions

프로그램을 만들다 보면 수없이 많은 오류를 만나게 된다. 물론 오류가 발생하는 이유는 프로그램이 잘못 동작되는 것을 막기 위한 파이썬의 배려이다. 하지만 때때로 이러한 오류를 무시하고 싶을 때도 있고 별도로 처리하고 싶을 때도 있다. 이에 파이썬은 try, except를 이용해서 오류를 처리할 수 있게 해준다.

오류가 발생하는 경우는?

파이썬은 매우 친절하게도 오류(Error) 타입을 분류해서 사용자에게 알려주고 있다.

그럼에도 불구하고 이런 친절함을 이해하지 못하고, 활용하지 못한다면 무슨 소용이 있을까 ?

이번엔 프로그램에서 자주 발생하는 오류의 예시를 살펴보고 오류를 처리하는 방법을 배워 보도록 한다.

IndexError

In [1]: list = []

In [2]: list[0]
-----------------------------------------------------------------
IndexError                      Traceback (most recent call last)
<ipython-input-2-3f96b4c58ba4> in <module>()
----> 1 list[0]

IndexError: list index out of range
  • 이 예제를 보면 빈 리스트에서 list[0]의 값을 가져오려고 하면 IndexError (색인오류)가 발생한다.

ValueError

In [3]: text = 'abc'

In [4]: number = int(text)
-----------------------------------------------------------------
ValueError                      Traceback (most recent call last)
<ipython-input-4-cad86af3a9b3> in <module>()
----> 1 number = int(text)

ValueError: invalid literal for int() with base 10: 'abc'
  • number 라는 변수에 text 변수 'abc'int로 바꾸려고 한다.

  • 'abc'는 숫자로 바꿀 수 없기 때문에 ValueError가 발생한다.

try / except

다음은 오류 처리를 위한 try, except문의 기본 구조이다.

에러가 발생할 것 같은 코드를 try: 아래 블럭에 놓고 except 에 발생할 수 있는 에러의 이름 NameError을 적어두면, 에러가 발생할 경우 별도로 처리해 줄 수 있다.

에러 처리를 해주지 않는다면 에러가 발생해 프로그램이 멈추는 불상사가 일어날 것이다.

text = "100%"
try:
    number = int(text)
except ValueError:
    print('{}는 숫자가 아닙니다.'.format(text))
    
---------------------------------------------------------------
> 100% 숫자가 아닙니다.

if / else

경우에 따라서 if / else로 바꿔 사용할 수 있다. 코드가 더 간결한 것을 선택해 사용한다.

# try-except 문
def safe_pop_print(list, index):
    try:
        print(list.pop(index))
    except IndexError:
        print('{} index의 값을 가져올 수 없습니다.'.format(index))

safe_pop_print([1,2,3], 5) #

------------------------------------------------------------------

> 5 index 값을 가져올  없습니다.

# if 문
def safe_pop_print(list, index):
    if index < len(list):
        print(list.pop(index))
    else:
        print('{} index의 값을 가져올 수 없습니다.'.format(index))

safe_pop_print([1,2,3], 5) 

------------------------------------------------------------------

> 5 index 값을 가져올  없습니다.

try /except 가 아니면 예외처리가 안되는 경우

try:
    import my_module
except ImportError:
    print("모듈이 없습니다.")

예외 이름과 상관 없이 에러처리


try:
  list=[]  
  print(list[0]) # 빈리스트의 값을 불러오는 경우 Error가 발생
  text = 'abc'
  number = int(text) # 문자열을 정수로 불러오면 Error가 발생 
except:
    print('에러가 발생했습니다.')
   

except.py

에러가 발생했습니다.

예외 이름을 모르는 경우 처리 방법

try:
    # 에러가 발생할 가능성이 있는 코드
except Exception as ex: # 에러 종류
    print('에러가 발생 했습니다', ex) # ex는 발생한 에러의 이름을 받아오는 변수
try:
  # list=[]
  # print(list[0])
  text = 'abc'
  number = int(text)
except Exception as ex:
    print('에러가 발생했습니다.', ex)

except.py

에러가 발생했습니다. invalid literal for int() with base 10: 'abc'
try:
  list=[]
  print(list[0])
  # text = 'abc'
  # number = int(text)
except Exception as ex:
    print('에러가 발생했습니다.', ex)

python except.py

에러가 발생했습니다. list index out of range

raise 예외 발생

raise를 통해 에러를 직접 발생시킨다.

def rsp(mine, yours):  # 나와 , 상대방
    allowed = ['가위','바위', '보']
    if mine not in allowed: # mine 에  '가위', '바위', '보' 중에 있는지 검사
        raise ValueError    # 없으면 ValueError 발생
    if yours not in allowed: # yours 에 '가위', '바위', '보' 중에 있는지 검사
        raise ValueError    # 없으면 ValueError 발생
    # 가위바위보 승패를 판단하는 코드
    
rsp('가위','바')

python raise.py

Traceback (most recent call last):
  File "raise.py", line 11, in <module>
    rsp('가위','바')
  File "raise.py", line 9, in rsp
    raise ValueError   
  ValueError
def rsp(mine, yours):  # 나와 , 상대방
    allowed = ['가위','바위', '보']
    if mine not in allowed: # mine 에  '가위', '바위', '보' 중에 있는지 검사
        raise ValueError    # 없으면 ValueError 발생
    if yours not in allowed: # yours 에 '가위', '바위', '보' 중에 있는지 검사
        raise ValueError    # 없으면 ValueError 발생
try:
    rsp('가위', '바')
except ValueError:
    print('잘못된 값을 넣었습니다.')

반복문이 중첩 되어있을때 - raise

# 반 안에 190이 넘는 학생이 있으면 반 이름을 출력하고 즉시, 프로그램을 종료한다.
school = {'1반': [172, 185, 198, 177, 165, 199], '2반':[165, 177, 167, 180, 191]}
for class_number, students in school.items(): 
    # class_number 에는 '반이름' , students 에는 [학생들의 키 list]가 대입된다.
    for student in students:
        if student>190:
            print(class_number, '반에 190을 넘는 학생이 있습니다.')
            break

python raise.py

1 반에 190 넘는 학생이 있습니다.

2 반에 190 넘는 학생이 있습니다.
school = {'1반': [172, 185, 198, 177, 165, 199], '2반':[165, 177, 167, 180, 191]}
try:
    for class_number, students in school.items():
        for student in students:
            if student>190:
                print(class_number, '반에 190을 넘는 학생이 있습니다.')
                raise StopIteration
                # 예외가 try: 블럭에 있지 않으면 에러 발생시 프로그램이 멈춘다.     
except StopIteration:
    print('정상종료')

python raise.py

1 반에 190 넘는 학생이 있습니다.

정상종료

:: 참고 강의 :: 파이썬 입문> try except