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하기 (307) | 2018.11.19 |
tensorflow 설치하기 (31) | 2018.09.19 |
[python] organize -1 (0) | 2018.06.18 |