[python] Python 2.6에서 더 이상 사용되지 않는 BaseException.message

다음 사용자 정의 예외를 사용하면 Python 2.6에서 BaseException.message가 더 이상 사용되지 않는다는 경고가 표시됩니다.

class MyException(Exception):

    def __init__(self, message):
        self.message = message

    def __str__(self):
        return repr(self.message)

이것은 경고입니다.

DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message

이게 뭐가 문제 야? 지원 중단 경고를 없애려면 무엇을 변경해야합니까?



답변

솔루션-코딩이 거의 필요 없음

예외 클래스를 상속 Exception하고 메시지를 생성자에게 첫 번째 매개 변수로 전달하십시오.

예:

class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    print my # outputs 'my detailed description'

str(my)또는 (아주 우아함) my.args[0]을 사용하여 사용자 지정 메시지에 액세스 할 수 있습니다 .

배경

최신 버전의 Python (2.6부터)에서는 Exception에서 사용자 정의 예외 클래스 ( Python 2.5부터 )가 BaseException에서 상속합니다. 배경은 PEP 352 에 상세하게 설명되어있다 .

class BaseException(object):

    """Superclass representing the base of the exception hierarchy.
    Provides an 'args' attribute that contains all arguments passed
    to the constructor.  Suggested practice, though, is that only a
    single string argument be passed to the constructor."""

__str__그리고 __repr__이미 특히 (메시지로 사용할 수 있습니다) 하나의 인수의 경우에, 의미있는 방식으로 구현됩니다.

다른 사람이 제안한대로 반복 __str__하거나 __init__구현하거나 만들 필요가 없습니다 _get_message.


답변

예, Python 3.0에서는 없어지기 때문에 Python 2.6에서는 더 이상 사용되지 않습니다.

BaseException 클래스는 더 이상 오류 메시지를 저장하는 방법을 제공하지 않습니다. 직접 구현해야합니다. 메시지 저장을위한 특성을 사용하는 서브 클래스로이를 수행 할 수 있습니다.

class MyException(Exception):
    def _get_message(self):
        return self._message
    def _set_message(self, message):
        self._message = message
    message = property(_get_message, _set_message)

도움이 되었기를 바랍니다


답변

class MyException(Exception):

    def __str__(self):
        return repr(self.args[0])

e = MyException('asdf')
print e

이것은 Python2.6 스타일의 클래스입니다. 새로운 예외는 임의의 수의 인수를 취합니다.


답변

경고를 복제하는 방법

질문의 샘플 코드로 이것을 복제 할 수 없으므로 문제를 분명히 해 보겠습니다. 경고를 켜면 ( -W플래그 , PYTHONWARNINGS환경 변수 또는 경고 모듈을 통해) Python 2.6 및 2.7에서 경고를 복제합니다 .

>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'

사용 중지 .message

repr(error)오류 유형의 이름, 메시지의 repr (있는 경우) 및 나머지 인수의 repr을 포함하는 문자열을 반환하는을 선호합니다 .

>>> repr(error)
"Exception('foobarbaz',)"

계속 사용하면서 경고 제거 .message

그리고 당신은 얻을 방법 제거 의는 DeprecationWarning파이썬 설계자가 의도 한대로 내장 예외를 서브 클래 싱하는 것입니다 :

class MyException(Exception):

    def __init__(self, message, *args):
        self.message = message
        # delegate the rest of initialization to parent
        super(MyException, self).__init__(message, *args)

>>> myexception = MyException('my message')
>>> myexception.message
'my message'
>>> str(myexception)
'my message'
>>> repr(myexception)
"MyException('my message',)"

.message없이 속성을 얻는 것error.message

예외에 대한 하나의 인수, 메시지가 있고 그것이 원하는 것을 알고 있다면, 메시지 속성을 피하고 str오류를 취하는 것이 좋습니다. 하위 클래스를 말하십시오 Exception.

class MyException(Exception):
    '''demo straight subclass'''

그리고 사용법 :

>>> myexception = MyException('my message')
>>> str(myexception)
'my message'

이 답변도 참조하십시오.

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


답변

내가 알 수있는 한, 메시지 속성에 다른 이름을 사용하면 기본 클래스와의 충돌을 피할 수 있으므로 사용 중단 경고가 중지됩니다.

class MyException(Exception):

def __init__(self, message):
    self.msg = message

def __str__(self):
    return repr(self.msg)

나에게 해킹처럼 보인다.

서브 클래스가 메시지 속성을 명시 적으로 정의한 경우에도 누군가 경고가 발행 된 이유를 설명 할 수 있습니다. 기본 클래스에 더 이상이 속성이 없으면 문제가 없어야합니다.


답변

geekQ의 답변 에서 계속해서 선호되는 코드 교체는 수행해야 할 작업에 따라 다릅니다.

### Problem
class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    ### Solution 1, fails in Python 2.x if MyException contains ?
    # with UnicodeEncodeError: 'ascii' codec can't encode characters in position 24-25: ordinal not in range(128)
    print(my)  # outputs 'my detailed description'

### Solution 2
# Works in Python 2.x if exception only has ASCII characters,
# should always work in Python 3.x
str(my)

### Solution 3
# Required in Python 2.x if you need to handle non-ASCII characters,
# such as δσφφδσ (as pointed out by jjc) or emoji ? ? ? ? ?
# but does not work in Python 3.x
unicode(my)

때로는 예외에 둘 이상의 논쟁이 있기 때문에 my.args[0] 모든 관련 정보를 제공하지는 않습니다.

예를 들어 :

# Python 2.7
try:
    u'\u12345'.encode('utf-8').encode('utf-8')
except UnicodeDecodeError as e:
    print e.args[0]
    print e.args
    print str(e)

출력으로 인쇄합니다 :

ascii
('ascii', '\xe1\x88\xb45', 0, 1, 'ordinal not in range(128)')
'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)

그러나 상황에 민감한 트레이드 오프입니다.

# Python 2.7
>>> str(SyntaxError())
'None'
# 'None' compares True which might not be expected


답변

str (myexception) 사용에 대한 조언은 파이썬 2.7에서 유니 코드 문제를 유발합니다.

str(Exception(u'δσφφδσ'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

🙁

unicode(Exception(u'δσφφδσ')) 

예상대로 작동하며 오류 문자열의 일부 내용에 사용자 입력이 포함 된 경우 선호