python - error - 파이썬 warnings




현대 Python에서 사용자 정의 예외를 선언하는 올바른 방법은 무엇입니까? (5)

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

"현대 파이썬"이란 파이썬 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__ 재정의하는 것이 좋습니다. 그건 타이핑이 많은 것처럼 보입니다. 필요합니까?


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

예외가 실제로보다 구체적인 예외 유형이 아니면 예외입니다.

class MyException(Exception):
    pass

또는 pass 대신에)를 쓰면 문서화가 가능합니다.

class MyException(Exception):
    """Raise for my specific kind of exception"""

예외 서브 클래스 서브 클래스하기

docs

Exception

모든 내장, 시스템 외 종료 예외는이 클래스에서 파생됩니다. 모든 사용자 정의 예외도이 클래스에서 파생되어야합니다.

즉, 예외가 더 구체적인 예외 유형 인 경우 일반 Exception 대신 해당 예외를 하위 클래스로 지정합니다. 결과는 문서에서 권장하는대로 Exception 에서 파생 된 결과입니다. 또한 최소한 docstring을 제공 할 수 있습니다 ( pass 키워드를 사용하지 않아도 됨).

class MyAppValueError(ValueError):
    '''Raise when my specific value is wrong'''

사용자 정의 __init__ 을 사용하여 직접 만든 속성을 설정하십시오. dict을 위치 인수로 사용하지 않으려면 이후 코드 사용자가 감사합니다. deprecated 메시지 속성을 사용하는 경우 직접 할당하면 DeprecationWarning 이 발생하지 DeprecationWarning .

class MyAppValueError(ValueError):
    '''Raise when a specific subset of values in context of app is wrong'''
    def __init__(self, message, foo, *args):
        self.message = message # without this you may get DeprecationWarning
        # Special attribute you desire with your Error, 
        # perhaps the value that caused the error?:
        self.foo = foo         
        # allow users initialize misc. arguments as any other builtin Error
        super(MyAppValueError, self).__init__(message, foo, *args) 

자신 만의 __str__ 또는 __repr__ 을 작성할 필요가 없습니다. 내장 된 것들은 매우 훌륭하며, 당신의 협력 상속 은 당신이 그것을 사용하도록 보장합니다.

최고 대답의 비판

어쩌면 질문을 놓쳤을 지 모르겠지만,

class MyException(Exception):
    pass

다시 말하지만, 위의 문제는 그것을 잡기 위해 구체적으로 이름을 지정하거나 (다른 곳에서 만든 경우 가져 오기) Exception을 잡아야한다는 것입니다 (하지만 모든 유형의 예외를 처리 할 준비가되지 않았을 수도 있습니다. 처리 할 준비가 된 예외 만 잡아야합니다. 아래에 비슷한 비판하지만, 또한 super 를 통해 초기화하는 방법이 아니므로 메시지 속성에 액세스하면 DeprecationWarning 됩니다.

편집 : 무언가를 무시 (또는 추가 args 전달)하려면 다음과 같이하십시오.

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

그런 식으로 두 번째 매개 변수에 오류 메시지를 전달하고 나중에 e.errors로 가져올 수 있습니다.

또한 전달할 정확히 두 개의 인수가 필요합니다 ( self 외에). 그것은 미래의 사용자가 이해하지 못할만한 흥미로운 제약입니다.

직접적으로 - Liskov 대체성에 위배 됩니다 .

두 가지 오류를 모두 설명하겠습니다.

>>> ValidationError('foo', 'bar', 'baz').message

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)

>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'

비교 대상 :

>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'

메시지를 사용하는 대신 __repr__ 또는 __unicode__ 메소드를 오버라이드해야합니다. 예외를 생성 할 때 제공하는 args 는 예외 객체의 args 속성에 있습니다.


어쩌면 질문을 놓쳤을 지 모르겠지만,

class MyException(Exception):
    pass

편집 : 무언가를 무시 (또는 추가 args 전달)하려면 다음과 같이하십시오.

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

그런 식으로 두 번째 매개 변수에 오류 메시지를 전달하고 나중에 e.errorse.errors

Python 3 Update : Python 3+에서는 약간 더 compact 한 super() 사용할 수 있습니다 :

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super().__init__(message)

        # Now for your custom code...
        self.errors = errors

이 예제를 시도하십시오.

class InvalidInputError(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return repr(self.msg)

inp = int(input("Enter a number between 1 to 10:"))
try:
    if type(inp) != int or inp not in list(range(1,11)):
        raise InvalidInputError
except InvalidInputError:
    print("Invalid input entered")

현대 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




exception