반응형

오류처리

다른 프로그래밍 언어와 마찬가지로 Python 코드에는 다양한 유형의 오류 및 예외가 발생할 수 있습니다.

일반적으로 Python 응용 프로그램의 오류는 컴파일 타임 오류와 런타임 오류의 두 가지 유형으로 나뉩니다.

컴파일 타임 오류는 응용 프로그램이 실행되기 전에 발생하고 런타임 오류는 응용 프로그램 실행 중에 발생합니다.

런타임 오류는 예외라고도 하며 응용 프로그램이 충돌할 가능성이 있습니다.

Python은 런타임에 데이터 유형이 평가되는 느슨한 유형의 언어이므로 Java C#과 같은 강력한 유형의 언어보다 예외가 발생할 가능성이 훨씬 더 높습니다.

 

예외처리

예외 처리는 응용 프로그램이 런타임에 충돌하지 않도록 하고 예외를 관리하는 프로세스로 정의할 수 있습니다.

예외 처리를 통해 응용 프로그램이 비정상적으로 작동하는 원인과 사용자가 응용 프로그램을 사용하여 수행하려는 작업에 대해 사용자에게 더 읽기 쉬운 메시지를 표시할 수 있습니다. 그럼 더 이상 고민하지 않고 시작하겠습니다.

 

다음 스크립트는 컴파일 타임 오류가 어떻게 보이는지 보여줍니다. 파이썬 인터프리터가 해석할 수 없기 때문에 실행되지 않습니다. 출력은 함수 매개변수가 대괄호로 지정되었기 때문에 코드에 구문 오류가 있음을 보여줍니다. 대괄호 안에 함수 매개변수를 지정해야 합니다.

 

def divide_numbers[a, b]:

  result = a / b

  print(result)

 

Output:

SyntaxError: invalid syntax

 

위의 스크립트의 오류를 수정하면 다음과 같습니다.

def divide_numbers(a, b):

  result = a / b

  print(result)

 

다음 스크립트를 실행하면 숫자를 0으로 나눌 수 없다는 오류가 발생합니다. 매개변수 b의 값으로 0을 전달할 때만 오류가 발생하는 것을 볼 수 있습니다. 이것은 예외의 예입니다.

 

def divide_numbers(a, b):

  result = a / b

  print(result)

 

divide_numbers(20, 0)

 

Output:

ZeroDivisionError: division by zero

 

예외처리 다루기

예외처리의 기본 구조는 try, exception문으로 구성되어 있습니다.

 

try:

실행 구문

except [발생 오류[as 오류 메시지 변수]]:

오류 메시지

 

try 블록 수행 중 오류가 발생하면 except 블록이 수행됩니다. 하지만 try 블록 수행 중 오류가 발생하지 않으면 except블록은 수행되지 않습니다.

 

1.     try , except만 쓰는 경우

오류 종류에 상관없이 오류가 발생하면 except블록이 수행됩니다.

 

try:

실행 구문

except :

오류 메시지

 

2.     발생 오류만 포함한 except

오류가 발생했을 때 except문에 미리 정해 놓은 오류 이름과 일치할 때만 except 블록을 수행합니다.

 

try:

실행 구문

except 발생오류:

오류 메시지

 

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

2번째 경우에서 오류 메시지의 내용까지 알고 싶을 때 사용하는 방법입니다.

 

try:

실행 구문

except 발생오류 as 오류 메시지 변수:

오류 메시지

 

 

Python 스크립트는 다양한 유형의 예외를 발생시킵니다. 예를 들어, 다음 스크립트는 두 가지 예외를 발생시킬 수 있습니다. 매개변수 b의 값으로 0을 전달하면 0으로 나누기 예외가 발생합니다. b에 대해 0이 아닌 값을 전달하면 다음 스크립트는 초기화되지 않은 "result_ new" 변수에 대한 값을 출력하는 예외가 발생합니다.

 

def divide_numbers(ab):

  result = a / b

  print(result_new)

 

다음 스크립트는 b0을 전달할 때 나누기 예외 발생한 경우입니다.

 

divide_numbers(20, 0)

 

Output:

NameError: name 'result_new' is not defined

 

다음 스크립트는 정상적으로 나눗셈이 이루어졌지만 result_new 변수가 초기화가 되어 있지 않아서 예외가 발생한 경우입니다.

 

divide_numbers(20, 10)

 

Output:

NameError: name 'result_new' is not defined

 

위의 예제를 보면 하나의 Python 스크립트가 여러 예외를 생성할 수 있음을 알 수 있습니다.

Python에서 예외를 처리하려면 예외를 발생할 가능성이 가장 높은 코드를 try 블록 내부에 감싸야 합니다. try 블록 다음에는 except 블록이 와야 합니다. 예외 블록에는 예외가 발생한 경우 실행하려는 코드가 포함되어 있습니다.

 

다음 스크립트는 Divide_numbers() 메서드 내에서 a b로 나누고 result_new 변수가 인쇄되는 코드가 try 블록 안에 있습니다. 예외가 발생한 경우 "예외가 발생했습니다."라는 메시지가 사용자에게 표시됩니다.

 

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except:

    print("an exception occurred")

 

b0을 전달하면 예외가 발생하게 되고 예외 문자가 출력됩니다.

divide_numbers(20, 0)

 

Output:

an exception occurred

 

b10을 전달하면 정상적으로 나눗셈은 이루어지지만 result_new변수가 초기화가 되지 않아서 예외가 발생하게 되고 예외 문자가 출력됩니다.

divide_numbers(20, 10)

 

Output:

an exception occurred

 

이전 스크립트에서 두 예외에 대해 동일한 메시지를 받았습니다. 다른 예외에 대해서 다른 메시지를 출력할 수 있습니다. 예외가 발생하면 Exception 클래스의 객체가 생성됩니다. 다음 스크립트와 같이 예외 블록에서 해당 객체를 사용하여 예외 메시지를 인쇄할 수 있습니다.

 

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except Exception as e:

    print(e)

 

divide_numbers(20, 0)

 

Output:

division by zero

 

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except Exception as e:

    print(e)

 

divide_numbers(20, 10)

 

Output:

name 'result_new' is not defined

 

다양한 예외를 개별적으로 처리하는 방법

다른 예외를 개별적으로 처리하고 예외 유형에 따라 except 블록에서 다른 코드를 실행할 수 있습니다.

 

다음 스크립트에는 NameError 예외와 ZeroDivisionError 예외를 잡는 두 개의 예외 블록이 있습니다. b0을 전달하면 ZeroDivisionError예외가 발생하게 됩니다.

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except NameError:

    print("변수를 사용하기 전에 초기화되지 않았습니다.")

  except ZeroDivisionError:

    print("0으로 나누는 것은 불가능합니다.")

 

divide_numbers(20, 0)

 

Output:

0으로 나누는 것은 불가능합니다.

 

정상적으로 나눗셈은 이루어졌지만 result_new변수가 초기화되지 않았기 때문에 NameError 예외가 발생하였습니다.

divide_numbers(20, 10)

 

Output:

변수를 사용하기 전에 초기화되지 않았습니다.

 

Finally 블록 사용

finally 블록은 예외 발생 여부에 관계없이 항상 실행됩니다.

finally 블록은 일반적으로 메모리 공간을 지우는 데 사용됩니다.

 

다음 스크립트에서는 Divide_numbers() 메서드 끝에 finally 블록을 추가했습니다.

def divide_numbers(ab):

  try:

    result = a / b

    print(result_new)

  except NameError:

    print("변수를 사용하기 전에 초기화되지 않았습니다.")

  except ZeroDivisionError:

    print("0으로 나누는 것은 불가능합니다.")

  finally:

    print("항상 실행됩니다.")

 

divide_numbers(20, 10)

 

Output:

변수를 사용하기 전에 초기화되지 않았습니다.

항상 실행됩니다.

 

사용자 정의 예외처리

사용자 정의 예외를 발생시키는 가장 간단한 방법은 "raise Exception" 키워드를 사용하는 것입니다. 예외에 대한 메시지는 Exception 클래스의 생성자로 전달됩니다.

raise 키워드를 사용해서 오류를 강제로 발생시킬 수 있습니다.

 

다음 스크립트는 목록 변수 my_list 3개 이상의 항목을 삽입하려고 하면 예외가 발생합니다. my_list 4개의 항목을 추가하므로 다음 스크립트의 출력과 같이 예외가 표시됩니다.

 

my_list = []

 

for _ in range(4):

  my_list.append("Python")

  print(my_list)

if len(my_list)>3:

    raise Exception("This list cannot contain more than 3 items")

 

Output:

['Python']

['Python', 'Python']

['Python', 'Python', 'Python']

['Python', 'Python', 'Python', 'Python']

Exception: This list cannot contain more than 3 items

 

Exception 클래스를 상속받아서 사용자 정의 예외처리 클래스 만들기

Exception 클래스에서 상속되는 클래스를 생성하여 사용자 지정 이름의 예외를 정의할 수 있습니다.

 

다음 스크립트에서는 Exception 클래스에서 상속되는 ListItemOverFlow라는 사용자 지정 예외에 대한 클래스를 정의합니다. 사용자 정의 클래스 생성자에서 사용자 정의 오류 메시지를 부모클래스인 Exception 클래스 생성자에 전달합니다.

 

class ListItemOverFlow(Exception):

  def __init__(selfnew_listerror_message="Exception: This list cannot contain more than 3 items"):

    self.new_list = new_list

    self.error_message = error_message

    super().__init__(self.error_message)

 

이제 ListItemOverFlow 예외를 throw하면 ListItemOverFlow 클래스 생성자 내에서 정의한 사용자 지정 메시지와 함께 출력에 명명된 예외가 표시됩니다.

 

my_list = []

 

for _ in range(4):

  my_list.append("Python")

  print(my_list)

  if len(my_list) > 3:

    raise ListItemOverFlow(my_list)

 

Output:

['Python']

['Python', 'Python']

['Python', 'Python', 'Python']

['Python', 'Python', 'Python', 'Python']

ListItemOverFlow: Exception: This list cannot contain more than 3 items

반응형

+ Recent posts