예외 처리
예외란 말 그대로 프로그램에서 벌어지는 예외적인 상황을 뜻한다.
예를 들자면 , 우리가 파일으 읽고자 할 때 그 파일이 존재하지 않는 경우라던지 , 또는 한참 프로그램이 실행중인데
그 파일을 갑자기 지워버렸다던지 하는 경우다. 이러한 상황을 처리해 주는 것을 예외 처리 라고 한다.
비슷하게 우리가 프로그램에 존재하지 않는 명령문이 있을 경우 어떻게 될까?
이런 경우 파이썬은 손을 들고( raise ) 프로그램에 오류 ( error ) 가 있다고 알려준다.
오류
간단히 print함수를 호출하는 상황을 생각해보자.
이 떄 print를 Print 라고 잘못 쳤을 경우 어떻게 될까?
SyntaxError ( 구문 오류 ) 가 발생되었고 오류가 발생한 위치가 표시될 것이다.
이것은 이 오류의 오류 핸들러에 의해 처리되는 것이다.
이번에는 사용자로부터 뭔가를 입력받는 것을 시도하는 경우를 생각해보자.
이때 ctrl - d 를 누르고 어떻게 되는지 살펴보자.
그러면 파이썬은 EOFError 라고 불리우는 오류를 발생시키는데 이때 EOF 란 파일의 끝 (End Of File)을 의미하며
(파일의 끝은 ctrl - d 에 의해 표현됨 ) ,
갑자기 파일의 끝이 올 것을 예상하지 못했기 때문에 오류가 발생하는 것이다.
try:
text= input('Enter something --> ')
except EOFError:
print('Why did you do an EOF on me?')
except KeyboardInterrupt:
print("You cancelled the operation.")
else:
print("You entered {}".format(text))
예제에서는 예외가 발생할 수 있는 모든 명령문을 try 블록에 넣어주었으며 오류/예외를 적절하게 처리해 줄 핸들러를 excpet 블록에 넣어주었다.
except절에서는 지정된 한개의 오류 혹은 예외를 처리할 수도 있고 , 괄호로 묶여진 모든 오류/예외 목록을 처리해줄 수도 있다.
만일 오류/예외가 지정되지 않은경우에는 모든 오류/예외를 처리하게 된다.
이때 모든 try 절에는 적어도 한개의 except절이 있어야 한다. 아니면 try블록을 사용할 이유가 없다..
만일 어떤 오류나 예외든지 이처럼 처리되지 않는 경우 , 기본 파이썬 오류 핸들러가 호출되는데 그러면
이에 의해 프로그램의 수행이 중단되며 해당되는 오류 메세지가 출력된다. 위에서 기본 파이썬 오류 핸들러가 어떻게 동작하는지 보았다.
또한 try..except 블록에는 추가로 else 절을 붙일수 있다. else 절은 어떤 예외도 발생하지 않았을 경우 호출된다.
class ShortInputException(Exception):
'''사용자가 지정한 예외 클래스'''
def __init__(self,length,atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
text = input("Enter Something:")
if len(text) <3:
raise ShortInputException(len(text),3)
except EOFError:
print("Why did you do an EOF on me?")
except ShortInputException as ex:
print("ShortInputException : The input was" + "{0} long,expected at least {1}".).format(ex.length,ex.atleast)
else:
print("No exception was raised")
위 예제에서는 ShortInputException 이라고 불리우는 새로운 예외 형식을 직접 하나 만들었다.
여기에는 2개의 필드가 있다. 하나는 length 필드로 주어진 입력의 길이를 의미하며 , 또 하나는 atleast 필드로 프로그램이 요구하는 최소한의 길이를 의미한다.
이제 except 절에서 as를 이용하여 해당 오류의 클래스를 좀 더 짧은 이름의 변수로 대신하여 사용할 수 있게 한다.
여기에 새로 정의한 예외 형식에 정의한 필드와 값의 관계는 함수에서의 매개변수와 인수의 관계와 비슷하다.
마지막으로 이 오류를 처리해주는 except 절에서는 해당 예외 객체의 length와 atleast 필드를 이용하여 사용자에게 적절한 결과를 출력해준다.
Try...Finally 문
프로그램 파일을 읽고 있는 상황을 가정해 보자 ,
이 떄 , 예외가 발생할 경우 , 예외의 발생 여부와 상관없이 파일 객체를 항상 닫아주도록 할수는 없을까?
이를 위해 finally 블록을 사용한다.
import sys
import time
f=None
try:
f=open("poem.txt")
while True:
line = f.readline()
if len(line) == 0:
break
print(line),
sys.stdout.flush()
print("Press ctrl + c now")
time.sleep(2)
except IOError:
print("Could not find file poem.txt")
except KeyboardInterrupt:
print("!! You cancelled the reading from the file.")
finally:
if f:
f.close()
print("Cleaning up : Closed the file")
아주 평범한 파일을 읽는 코드를 작성하였지만 ,
파일에서 한 줄을 읽어올 때마다 time.sleep 함수를 호출하여 2초씩 멈추게 하는 인위적인 코드를 집어넣어 프로그램이 천천히 실행되도록 해 주었다. ( 파이썬은 원래 매우 빠름 )
프로그램이 실행중일 때 , ctrl + c 를 눌러 프로그램을 강제로 중단시켜 보자.
그러면 KeyboardInterrupt 예외가 발생되며 프로그램이 종료된다. 그러나 프로그램이 종료되게 전에 finally 절이 실행되므로
파일 객체가 안전하게 항상 닫히게 된다.
여기서 print문 뒤에 sys.stdout.flush() 를 사용하여 화면에 결과를 바로바로 출력하도록 해줬다.
'Programming > Python' 카테고리의 다른 글
Linked List (0) | 2019.10.02 |
---|---|
표준 라이브러리 (0) | 2017.11.13 |
입력과 출력 (0) | 2017.11.13 |
상속 (0) | 2017.11.13 |
클래스 변수와 객체 변수 (0) | 2017.11.13 |