본문 바로가기

나 취준생/파이썬

파이썬 오류 처리 ( try~except, else, finally, exception as e, 특정 예외)

320x100

# 예외처리


프로그램을 작성하다보면 뜻하지 않은 오류가 발생하는 코드가 있다.

프로그램이 실행되는 동안 오류가 발생하면

프로그램이 더 이상 진행될 수 없는 상태가 되는데 이를 예외 상황이라고 한다.


프로그램에 예외가 발생하더라도 프로그램을 중단시키지 않고

예외에 대한 적절한 처리를 하여 프로그램을 계속 진행시키게 하는 구문이

try~except이다.


try:

    문제가 없을 경우 실행할 코드

except:

    문제가 생겼을 때 실행할 코드


try와 except 사이의 코드가 실행이 잘 되었다면

except 이후의 문장은 실행되지 않는다.


오류의 상황을 주기 위해서, 오류가 발생할 만한 상황을 만들어보자. 



1
2
3
4
5
def my_divide():
    x=input('분자의 숫자를 입력하세요~')
    y=input('분모의 숫자를 입력하세요~')
    return int(x)/int(y)
print(my_divide())




간단한 나누기 프로그램을 만들어본 뒤에,

10을 0으로 나누려고 하면,

다음과 같이 오류가 발생한다.


그럼 이제, try~except 문을 활용해서 오류에 대한 처리를 해보자.


1
2
3
4
5
6
7
8
def my_divide():
    try:
        x=input('분자의 숫자를 입력하세요~')
        y=input('분모의 숫자를 입력하세요~')
        return int(x)/int(y)
    except:
        return '0으로 나눌 수 없습니다'
print(my_divide())




그럼 다음과 같이 except 문에 넣은 return 문이 실행된다.

return 대신에 print를 바로 넣어 실행시켜도 된다.

대신 그럴 경우는 마지막 print()를 벗겨주어야 한다.



# else 문


else문을 사용하면 except절이 실행되지 않았을 경우

마지막에 else 문 안의 문장을 실행한다.


1
2
3
4
5
6
7
try:
    n=int(input('숫자를 입력하세요 : '))
    print(n**2)
except:
    print('숫자를 입력해주세요')
else:
    print('오류가 발생하지 않았습니다')




# finally 문


오류 발생 유무와 상관없이 어떤 코드를 무조건 실행시키려면

try~except~finally 구문을 활용한다.

따라서 무조건 실행시키고 싶은 코드는 fianlly 부분에 작성하면 된다.


1
2
3
4
5
6
7
8
9
10
try:
    x=int(input('분자의 숫자를 입력하세요'))
    y=int(input('분모의 숫자를 입력하세요'))
    print(x/y)
except:
    print('나누기를 할 수 없습니다')
else:
    print('성공적')
finally:
    print('프로그램 종료')



    


try-else-finally(오류 발생x)                   try-except-fianlly(오류 발생o)



# Exception as e


코드에서 예외가 발생하면 이에 대한 자세한 내용을 파악하는 것이 중요하다.

파이썬은 발생 가능한 예외에 대해 미리 정의해두고 있는데

이에 대한 내용은 다음 링크에서 확인할 수 있다.


https://docs.python.org/3/library/exceptions.html


위의 사이트에서 여러가지 에러를 찾고

미리 예외 처리를 할 수 있도록 정의해놓은 예외들을 확인할 수 있다.


1
2
3
4
5
6
try:
    x=int(input('분자의 숫자를 입력하세요 : '))
    y=int(input('분모의 숫자를 입력하세요 : '))
    print(x/y)
except:
    print('나누기를 할 수 없습니다')





위의 경우에는 분모 값을 입력할 때 숫자 0을 입력했을 떄와 문자 a를 입력했을때

똑같이 '나누기를 할 수 없습니다' 라고 출력되게 했는데

0을 입력했을 때와 a를 입력했을 경우 발생하는 에러의 종류는 분명 다른 것이다.

그래서 오류의 종류에 따라 그 원인을 더 자세하게 출력할 수 있다면, 다른 사용자가 에러의 원인을 더 자세히 파악할 수 있다.


1
2
3
4
5
6
7
8
try:
    x=int(input('분자의 숫자를 입력하세요 : '))
    y=int(input('분모의 숫자를 입력하세요 : '))
    print(x/y)
except ZeroDivisionError:
    print('0으로 나눌 수 없습니다')
except:
    print('잘못된 값을 입력하셨습니다')




이렇게 except 뒤에 에러의 종류를 입력해주면, 그 종류의 에러가 발생했을 경우 별도로 처리해줄 수 있다.

그리고 다른 나머지 오류들은 전부 except에서 처리할 수 있다.


이렇게 내가 직접 오류의 이유를 설명하는 방법도 있지만

컴퓨터의 저장된 오류를 보여주는 방식도 있다.



1
2
3
4
5
try:
    for i in range(1,int(input('숫자를 입력하세요~ : '))+1):
        print(i)
except:
    print('잘못된 값을 입력하셨습니다')





이런 보통의 코드의 경우, 에러에 대한 정확한 원인을 파악하기 힘들다. (잘못된 값이 뭐지?)


하지만


1
2
3
4
5
6
try:
    for i in range(1,int(input('숫자를 입력하세요~ : '))+1):
        print(i)
except Exception as e:
    print('잘못된 값을 입력하셨습니다')
    print(e)




이렇게 Exception as e 를 한 뒤

print(e) 까지 해주면 원인까지도 자세하게 보여줄 수가 있다.



특정 예외 처리


파이썬 입장에서 봤을 때는 오류가 아니지만

프로그래머가 이건 오류라고 일부러 프로그램이 돌지 않게 하기 위해서

오류 메세지를 출력하는 경우에 주로 사용한다.


ex) 어떤 중요한 데이터를 계산하는 프로그램에서 코드를 실행하던 도중에

(파이썬 입장에서는 오류가 아닌) 오류가 발생해버리면 잘못된 결과가 나올 수가 있다.

그래서 오류가 발생하면 끝까지 돌리지말고, 아예 멈춰버리라고 하는 것이다.


현업에서 이상한 결과가 나오는 것보다 아예 안 나오는게 정말 중요하다. (사고 발생)



* 실행 코드


if 조건:

raise Exception('예외가 발생했습니다.') # 여기서 종료

else:

실행 코드




* emp 사원의 이름과 월급을 출력하기


1
2
3
4
import pandas as pd
emp=pd.read_csv("c:\\data\\emp3.csv")
name=input('이름을 입력하세요~ : ')
print(emp[['ename','sal']][emp['ename']==name.upper()])




여기서 사용자 정의 예외처리를 해서

월급이 고소득자인 사원의 월급은 볼 수 없도록 메세지를 띄우고 실행을 멈추게 해보자



1
2
3
4
5
6
7
8
import pandas as pd
emp=pd.read_csv("c:\\data\\emp3.csv")
name=input('이름을 입력하세요~ : ')
result=emp[['sal']][emp['ename']==name.upper()].values[0]
if result>=3000:
    raise Exception('해당 사원의 월급은 볼 수 없습니다')
else:
    print(emp[['ename','sal']][emp['ename']==name.upper()])



result 절의 조건 절의


emp[['sal']][emp['ename']==name.upper()].values[0] --> .values[0]이 없으면


특정 사원의 월급값만 반환하는 것이 아니라

다른 데이터 pandas 형태로 출력한다. 그래서 조건을 넣어도 3000이 아니라 다른 값으로 인식해서

결과 값이 조회되지 않는다.

이럴 때 그 조건 뒤에 .values[0]을 해주면 그 값인 3000만 반환해서 조건절에서도 사용할 수가 있다.




이를 활용하면 이렇게 3000 이상인 scott은 오류가 발생해서 조회되지 않고,

그 이하인 smith는 이름과 월급이 출력된다.




이번에는 사원의 직업을 출력하는데

직업이 SALESMAN인 사원은 조회되지 않도록 해보자



1
2
3
4
5
6
7
8
import pandas as pd
name=input('이름을 입력하세요~ : ')
emp=pd.read_csv("c:\\data\\emp3.csv")
result=emp['job'][emp['ename']==name.upper()].values[0]
if result=='SALESMAN':
    raise Exception('해당 사원의 정보는 볼 수 없습니다')
else:
    print(emp['job'][emp['ename']==name.upper()].values[0])




직업이 SALESMAN인 ALLEN은 출력이 되지 않게 되었다.



이런 경우도 있을 수 있다.

한 번 사원의 이름을 emp 사원에 없는 aaa를 넣어보면,

1
2
3
4
import pandas as pd
name=input('사원 이름을 입력하세요 : ')
emp=pd.read_csv("c:\\data\\emp3.csv")
print(emp[['ename','sal']] [ emp['ename'== name.upper()])




이렇게 오류는 아니지만, 내가 원하지 않는 엉뚱한 데이터 프레임이 표시되어 버린다.


이럴 때는,


1
2
3
4
5
6
7
8
import pandas as pd
try:
    name=input('사원 이름을 입력하세요 : ')
    emp=pd.read_csv("c:\\data\\emp3.csv")
    result=emp['ename'] [emp['ename'== name.upper()].values[0]
    print(emp[['ename','sal']] [emp['ename'== result])
except LookupError:
    print('해당 사원은 없습니다')




아까처럼 .values[0]을 사용하면 된다.

values[0]을 사용하지 않으면 값이 아닌 데이터 프레임으로 나와서 오류라고 인식하지 않는다.

그래서 없는 사원 이름인 aaa를 입력하면, result에 값이 입력되지 않게 되므로

LookupError 예외 처리가 되어서 '해당사원은 없습니다' 라는 메세지가 출력된다.



반응형