[Python] 예외 처리

ㅎㅎ·2021년 5월 24일
0

Python

목록 보기
19/27




📌 예외 처리

  • 프로그램을 만들다 보면 오류가 발생하는데 이때 오류가 발생하는 이유는 프로그램이 잘못 동작하는 것을 막기 위함이다. 하지만 파이썬에서는 이러한 오류를 try,except를 통해 예외적으로 오류를 처리할 수 있다.

📌 오류 예외 처리 기법

- try , except문

  • try 블록 수행 중 오류가 발생하면 except 블록이 수행된다. 하지만 try 블록에서 오류가 발생하지 않으면 except 블록은 수행되지 않는다.
  • [] 기호가 존재하는데, 이 기호는 괄호 안의 내용을 생략할 수 있다는 관례 표기법이다.
try:
    ...
except [발생 오류[as 오류 메시지 변수]]:
    ...   

1) try , except만 쓰기

try:
	...
except:
	...
    

2) 발생 오류를 포함한 except문

try:
	...
except 발생오류:
	...

➡️ 이 경우는 오류가 발생했을때 except문에 미리 정해 놓은 오휴이름과 일치할 때만 except 블록을 수행한다는 뜻이다.

3) 발생 오류와 오류 메시지 변수까지 포함한 except문

try:
	...
except 발생 오류 as 오류 메시지 변수:
	...
       
#예시
try:
    4 / 0
except ZeroDivisionError as e:
    print(e) #오류가 발생하면 변수(e)에 담기는 오류메세지를 출력하라. division by zero출력 됨

➡️ 이 경우는 두번째 경우에서 오류 메시지의 내용까지 알고 싶을때 사용하는 방법이다.

- try, finally 문

  • finally절은 try문 수행 도중 예외 발생 여부에 상관없이 항상 수행된다. 보통 finally절은 사용한 리소스를 close해야 할때에 많이 사용한다.
f = open('foo.txt', 'w')
try:
    # 무언가를 수행한다.
finally: # 항상 수행
    f.close()

➡️ "foo.txt"파일을 쓰기 모드로 연 후 try문을 수행한 후 예외 발생 여부와 상관없이 finally 절에서 f.close()로 열린 파일을 닫을 수 있다.

- 여러개의 오류처리하기

try:
    ...
except 발생 오류1:
   ... 
except 발생 오류2:
   ...
# 예시 1
try:
    a = [1,2]
    print(a[3]) #2개임 인덱싱 오류
    4/0 # 위에서 이미 오휴가 발생해서 오류 발생 X
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
except IndexError:
	print("인덱싱 할 수 없습니다.")

#예시 2
try:
    a = [1,2]
    print(a[3])
    4/0
except ZeroDivisionError as e:
    print(e)
except IndexError as e: 
    print(e) # list index out of range 출력

#예시 3
try:
    a = [1,2]
    print(a[3])
    4/0
except (ZeroDivisionError, IndexError) as e: #예시2(2개이상의 오류)를 묶어서 처리 가능
    print(e) # list index out of range 출력

- try, else문

  • try문 수행중 오류가 발생하면 except절이 수행되고, 오류가 없으면 else절이 수행된다.
try:
    ...
except [발생 오류[as 오류 메시지 변수]]:
    ...
else:  # 오류가 없을 경우에만 수행된다.
    ...
try:
    age=int(input('나이를 입력하세요: '))
except: # 숫자가 아닌 값
    print('입력이 정확하지 않습니다.')
else: # 숫자, 오류가 없을때만 수행된다. 
    if age <= 18:
        print('미성년자는 출입금지입니다.')
    else:
        print('환영합니다.')

📌 오류 회피하기

  • 프로그래밍을 할때 특정 오류가 발생할 경우 그냥 통과시켜야 할 때가 있다.
try:
    f = open("나없는파일", 'r') # 파일없음 
except FileNotFoundError:
    pass

➡️ 파일이 없기 때문에 FileNotFoundError:이라는 오류가 떠야하지만 pass를 사용해서 오류를 회피했다.


📌 오류 일부러 발생시키기

  • 종종 오류를 강제로 발생시켜야 할 경우가 생기면 raise명령어를 사용해 오류를 강제로 발생시킬 수 있다.
  • 예를들어 Bird 클래스를 상속받는 자식 클래스는 반드시 fly함수를 구현하도록 만들고 싶은 경우에는 ,
class Bird:
    def fly(self):
        raise NotImplementedError
# bird클래스를 상속받는 자식 클래스는 반드시 fly함수를 구현해야한다는 의지를 보여줌.
# 만약 자식 클래스가 fly함수를 구현하지 않은 상태로 fly함수를 호출한다면 어떻게 될까?

class Eagle(Bird): # bird클래스를 상속받음. 
    pass # 그러나 fly함수를 구현하지 않았음. 

#실행
eagle = Eagle()
eagle.fly()

➡️ 결과는 NotImplementedError로 이는 파이썬 내장 오류로, 꼭 작성해야 하는 부분이 구현되지 않았을 경우 일부러 오류를 일으켜 보여줌.

class Bird:
    def fly(self):
        raise NotImplementedError
        
#오류를 발생시키지 않으려면 eagle클래스에 fly함수를 반드시 구현해야함. 
class Eagle(Bird): # bird클래스를 상속받음. 
    def fly(self): #fly함수 구현
        print("very fast")
        
#실행
eagle = Eagle()
eagle.fly()

➡️ 반면에 fly함수를 구현했을때는, very fast라는 문장이 정상적으로 출력된다.


📌 예외 만들기

  • 프로그램 수행 도중 특수한 경우에만 예외 처리를 하기 위해서 종종 예외를 직접 만들어서 사용한다. 이때 예외를 파이썬 내장 클래스인 Exception 클래스를 상속하여 만들 수 있다.
class MyError(Exception): 
    pass

def say_nick(nick):
    if nick == '바보':
        raise MyError() #바보면 에러
    print(nick)
#실행
say_nick("천사")
say_nick("바보")
#결과
천사
Traceback (most recent call last):
  File "/Users/princesong/Desktop/Algorithm/python/p.py", line 10, in <module>
    say_nick("바보")
  File "/Users/princesong/Desktop/Algorithm/python/p.py", line 6, in say_nick
    raise MyError()
__main__.MyError

➡️ 이 프로그램을 실행하면 "천사"가 정상적으로 출력된 후 Myerror가 뜬다.

#예외처리기법 사용
try:
    say_nick("천사")
    say_nick("바보")
except MyError: #에러가 발생하면 출력
    print("허용되지 않는 별명입니다.")
    
    
#결과 - 정상 출력
천사
허용되지 않는 별명입니다.

➡️ 이때는 예외처리기법을 사용해 정상적으로 출력할 수 있다.

  • 또 다른 방법으로 오류메시지를 사용하고 싶다면 에외처리기법을 다르게 하면 된다.(try,except문의 3번 참고)
# 오류 메시지를 표현하고 싶을때는, 
try:
    say_nick("천사")
    say_nick("바보")
except MyError as e:
    print(e)
 #결과
 오류 메세지 출력 X

➡️ 하지만 실행했을때 오류메세지가 출력되지 않는다. 이렇게 오류 메시지를 출력했을때 오류메시지가 보이게 하려면 오류 클래스에 __str__메서드를 구현해야 한다. __str__ 메서드는 print(e)처럼 오류 메시지를 print문으로 출력할 경우에 호출되는 메서드이다.

class MyError(Exception):
    def __str__(self): # 위 코드에서 메서드만 추가함.
        return "허용되지 않는 별명입니다."
        
def say_nick(nick):
    if nick == '바보':
        raise MyError()
    print(nick)

try:
    say_nick("천사")
    say_nick("바보")
except MyError as e:
    print(e)
    
#결과
천사
허용되지 않는 별명입니다.

0개의 댓글