exception 파이썬 raise - 현대 Python에서 사용자 정의 예외를 선언하는 올바른 방법은 무엇입니까?





3 Answers

현대 Python 예외를 사용하면 .message 를 남용하거나 .__str__() 또는 .__repr__() 또는 그 중 하나를 무시할 필요가 없습니다. 예외가 발생했을 때 원하는 모든 정보 메시지가 있으면 다음과 같이하십시오.

class MyException(Exception):
    pass

raise MyException("My hovercraft is full of eels")

MyException: My hovercraft is full of eels 끝나는 추적을 제공합니다 MyException: My hovercraft is full of eels 합니다.

예외로부터 더 많은 유연성을 원하면 사전을 인수로 전달할 수 있습니다.

raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})

그러나 except 블록의 세부 정보를 얻는 것은 좀 더 복잡합니다. 세부 사항은 목록 인 args 속성에 저장됩니다. 다음과 같이해야합니다.

try:
    raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})
except MyException as e:
    details = e.args[0]
    print(details["animal"])

예외에 여러 항목을 전달하고 튜플 색인을 통해 액세스 할 수는 있지만 이것이 권장 되지 않습니다. 하나 이상의 정보가 필요하고 위의 메소드가 충분하지 않은 경우 tutorial 설명 된대로 Exception 하위 클래스를 만들어야합니다.

class MyError(Exception):
    def __init__(self, message, animal):
        self.message = message
        self.animal = animal
    def __str__(self):
        return self.message
warnings assert isinstance

현대 파이썬에서 커스텀 예외 클래스를 선언하는 적절한 방법은 무엇입니까? 내 기본 목표는 다른 표준 클래스를 따르는 것이므로 예외에 포함 된 추가 문자열은 예외를 포착 한 도구로 인쇄됩니다.

"현대 파이썬"이란 파이썬 2.5에서 실행될 것이지만 파이썬 2.6과 파이썬 3에서는 올바른 것입니다. * 일을하는 방식. 그리고 "custom"은 오류의 원인에 대한 추가 데이터를 포함 할 수있는 Exception 객체를 의미합니다. 문자열, 예외와 관련된 임의의 다른 임의의 객체 일 수 있습니다.

Python 2.6.2에서 다음과 같은 deprecation 경고로 인해 문제가 발생했습니다.

>>> class MyError(Exception):
...     def __init__(self, message):
...         self.message = message
... 
>>> MyError("foo")
_sandbox.py:3: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6

BaseExceptionmessage 라는 속성에 특별한 의미를 갖는 것은 BaseException 것처럼 보입니다. 나는 PEP-352 에서 속성이 2.5에서 특별한 의미를 가지고 있다는 것을 모았습니다. 그래서 그들은 그 이름을 (그리고 저 혼자서) 금지되었습니다. 응.

나는 또한 Exception 가 일부 마법 매개 변수 args 가지고 있다는 것을 모호하게 알고있다. 그러나 나는 그것을 사용하는 방법을 결코 알지 못했다. 앞으로 나아갈 일이 올바른 방법이라고 확신하지도 않습니다. 필자가 온라인에서 발견 한 많은 토론에서 Python 3에서 args를 제거하려고 시도했다고 제안했습니다.

업데이트 : 두 가지 답변으로 __init____str__ / __unicode__ / __repr__ 재정의하는 것이 좋습니다. 그건 타이핑이 많은 것처럼 보입니다. 필요합니까?




하나 이상의 속성이 사용되는 경우 예외가 어떻게 작동 하는지를보십시오 (역 추적은 생략됩니다) :

>>> raise Exception('bad thing happened')
Exception: bad thing happened

>>> raise Exception('bad thing happened', 'code is broken')
Exception: ('bad thing happened', 'code is broken')

그래서 당신은 일종의 " 예외 템플릿 "을 가지고 있고, 예외적 인 방식으로 호환되는 방식으로 작업 할 수 있습니다 :

>>> nastyerr = NastyError('bad thing happened')
>>> raise nastyerr
NastyError: bad thing happened

>>> raise nastyerr()
NastyError: bad thing happened

>>> raise nastyerr('code is broken')
NastyError: ('bad thing happened', 'code is broken')

이 서브 클래스로 쉽게 할 수있다.

class ExceptionTemplate(Exception):
    def __call__(self, *args):
        return self.__class__(*(self.args + args))
# ...
class NastyError(ExceptionTemplate): pass

그 기본 튜플과 같은 표현이 마음에 들지 않는다면 ExceptionTemplate 클래스에 __str__ 메소드를 추가하면됩니다 :

    # ...
    def __str__(self):
        return ': '.join(self.args)

너는 가질거야.

>>> raise nastyerr('code is broken')
NastyError: bad thing happened: code is broken



아니요, "메시지"는 금지되어 있지 않습니다. 그냥 비난 받았어. 응용 프로그램은 메시지를 사용하여 정상적으로 작동합니다. 그러나 물론 비추천 오류를 없앨 수 있습니다.

응용 프로그램에 대한 사용자 정의 Exception 클래스를 만들면 Exception에서 서브 클래 싱하지 않고 ValueError 또는 이와 유사한 객체에서 하위 클래스로 분류 할 수 있습니다. 그런 다음 변수 사용에 적응해야합니다.

그리고 응용 프로그램에 많은 예외가있는 경우 모듈의 사용자가 할 수 있도록 모든 모듈에 공통적 인 사용자 정의 기본 클래스를 사용하는 것이 좋습니다.

try:
    ...
except NelsonsExceptions:
    ...

그리고이 경우 __init__ and __str__ 필요하므로 모든 예외에 대해 반복하지 않아도됩니다. 그러나 message 변수를 message가 아닌 다른 것을 호출하는 것은 그 트릭을 수행합니다.

어떤 경우 든 Exception 자체가하는 것과는 다른 일을 할 경우 __init__ or __str__ 만 필요합니다. 그리고 비추천하면 두 가지 모두 필요하기 때문에 오류가 발생합니다. 클래스별로 필요한 추가 코드가 많이 없습니다. ;)




Related