Programming$

python exception 처리

ch4rli3kop 2022. 10. 21. 16:52
반응형

python exception 처리

이제까지 python 코드를 근본없이 작성하다가, 요즘 프로젝트를 하면서 파이썬 개발 디자인 모델이나 pythonic 하게 코드를 작성하는 팁을 찾아보고 있다.

요 글은 python의 exception을 어떻게 하면 좋게 처리할 수 있을까에 대해 나름 개인적으로 고민도 하고 서칭하면서 찾아본 내용을 간단하게 정리한 글이다. (반박시 그대의 말이 다 맞음)

case 1 : exception inheritance

exceptions.py

class dummyclass(Exception): 
 pass
​
class testException(dummyclass):
 def __str__(self) -> str:
   return f'testException'
​
class testException2(testException):
 def __str__(self) -> str:
   return f'testException2'
​
 def __repr__(self) -> str:
   return f'zzz'

main.py

from .exceptions import testException, testException2
​
if __name__ == '__main__':
 try:
   raise testException2
 except testException:
   print('zzz')
# zzz

상속관계에 있을 때, 하위 exception을 상위 exception으로 catch 할 수 있음.

case 2 : exception 클래스 비교

from .exceptions import testException, testException2
​
if __name__ == '__main__':
 try:
   raise testException2
 except testException as e:
   if e.__class__ is testException2:
     print('zzz')
# zzz

__class__ property를 사용하여 클래스 타입 비교를 할 수 있음. 상위 exception으로 catch 한 뒤에 하위 exception으로 비교.

case 3 : exception decorator

함수에 대해 exception 처리를 위해서 decorator를 사용하여 코드를 간결하게 할 수 있음.

python의 decorator는 함수의 실행 전, 실행 후 작업을 반복적으로 처리할 때 유용하게 사용할 수 있는 기능임. 아래 경우는 try-exception을 직접적으로 모든 함수에 적용하지 않고 decorator를 통해 간결하게 처리함.

단순 raise

exception이 발생했을 때, 단순히 raise 시키기 위한 decorator 함수

#!/usr/bin/python3
​
def testdecorate(function):
def wrapper(self, *args, **kwargs):
   try:
     return function(self, *args, **kwargs)
   except exception as e:
     raise e
 return wrapper
​
class TestClass:
 
 @testdecorate
 def testFunction(self):
   # do something

혹은 해당 클래스에 대한 사용자 정의 exception을 사용할 수도 있음.

from .exceptions import testException
​
def testdecorate(function):
def wrapper(self, *args, **kwargs):
   try:
     return function(self, *args, **kwargs)
   except exception as e:
     raise testException
 return wrapper
​
class TestClass:
 
 @testdecorate
 def testFunction(self):
   # do something

사용자 정의 exception raise

각 함수에 대해서 사용자 정의 exception을 인자로 줘서 raise 하고 싶을 때도 있을 수 있음. 이 경우 decorator에 exception을 인자로 넘겨줘야 해서 위와 조금 다르게 decorator를 작성해야 함.

from .exceptions import testException
​
def raiseExceptionDecorator(exception):
   def decorator(function):
       def wrapper(self, *args, **kwargs):
           try:
               return function(self, *args, **kwargs)
           except :
               raise exception
       return wrapper
   return decorator
 
​
class TestClass:
 
 @raiseExceptionDecorator(testException)
 def testFunction(self):
   # do something

인자로 사용자 정의 exception을 전달하면 해당 exception을 발생시킴.

exception handler 전달

exception에 대해서 따로 handler를 등록해서 처리하고 싶다면, 다음과 같이 사용할 수 있음. class 마다 method에서 발생한 exception을 처리하고자 하는 경우도 있을 수 있기 때문에, 다음과 같이 exception과 handler를 decorator의 인자로 전달하여 사용하면 됨.

from .exceptions import testException
​
def raiseExceptionDecorator(exception, handler):
   def decorator(function):
       def wrapper(self, *args, **kwargs):
           try:
               return function(self, *args, **kwargs)
           except :
               handler(exception)
       return wrapper
   return decorator
 
class TestClass:
 
 def exception_handler(self, e):
   print('eeee')
 
 @raiseExceptionDecorator(testException, exception_handler)
 def testFunction(self):
   # do something

Conclusion

exception handler와 exception 코드는 한 곳에 몰아넣는 것이 좋고 (ex. exceptions.py), 프로젝트 내의 모듈마다 작성하는게 좋을 듯하다. 데코레이터의 경우 위에서 단순히 raise를 하는 패턴, 인자를 전달하는 패턴 등 몇 가지를 나열했는데, 저 중 한가지 방법으로 통일해서 exception 처리를 하는게 깔끔할 것이다. 또한, exception을 어떻게 하느냐뿐만 아니라 어디서 하느냐도 중요한데, 이 부분은 추후에 파이썬 디자인 모델을 정리하면서 정리해야겠다.

반응형

'Programming$' 카테고리의 다른 글

[python] membership 관련  (0) 2022.11.02
Frida Example  (0) 2020.05.11
python byte reverse하기  (0) 2018.11.19
tensorflow 설치하기  (0) 2018.09.19
[python] organize -1  (0) 2018.06.18