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


177

다음 사용자 정의 예외를 사용하면 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

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


9
이유는 PEP 352를 참조하십시오 : python.org/dev/peps/pep-0352/#retracted-ideas
balpha

답변:


154

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

예외 클래스를 상속 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.


5
@Matt가 제안한 BaseException을 Exception으로 변경
geekQ

8
str유니 코드 인수로 예외가 구성된 경우 중단 사용 : str(MyException(u'\xe5'))raises UnicodeEncodeError. UnicodeDecodeError가 발생 하기 때문에 unicode대신 대신 사용 하는 str것이 절대 아닙니다 unicode(MyException('\xe5')). 이것은 인수가 str또는 인지 여부를 미리 알 수 없다면 이전에 사용한 위치 unicode를 사용해야 한다는 것을 의미합니까 ? .args[0].message
kasperd

1
@kasperd 거의 모든 파이썬 유니 코드 문제와 마찬가지로, 이것은 유니 코드 샌드위치 로 해결할 수 있습니다 .
Ryan P

3
@RyanP 그것은 실제로 들어가는 것을 제어 할 수 있다고 가정합니다. 여기 제가 직면 한 삶의 사실이 있습니다. 여러 타사 라이브러리의 예외를 처리해야합니다. 그중 일부는 예외에 유니 코드를 전달하고 일부는 str을 전달합니다. 라이브러리 중 하나에는 유니 코드에서 상속되는 자체 클래스가 있지만 사양에 필요한 str 대신 유니 코드를 반환하는 자체 repr 메서드가 있습니다.
kasperd

1
나는 btw했다. .message프로젝트 의 모든 사용법을 로 .args[0]바꾸면 아무런 문제가 발생하지 않습니다.
kasperd

26

예, 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)

도움이 되었기를 바랍니다


1
제기하는 동안 메시지를 어떻게 초기화 하시겠습니까? 그의 코드는 ( "일부 메시지") MyException를 호출하여 설정되는 메시지를 보여 주었다
eric.frederich을

내 예제의 메소드는 메시지 특성을 구현하기위한 것입니다. 속성 사용 방법은 코더에 달려 있습니다. 이 경우 OP는 코드에 게시 한 initstr 메소드를 사용합니다 .
Sahas

1
다른 변수 만 읽는 경우 getter / setter 대신 공용 변수를 사용하십시오. @property캡슐화가 필요할 때 언제든지 나중에 구문으로 업그레이드 할 수 있습니다 .
vdboor

2
@ vdboor : 그는 @property지원 중단 경고를 비활성화하는 데 사용하고 있습니다.
bukzor

값을 가져오고 설정하지 않고 선택하지 않고 변경하지 않는 속성을 만드는 것은 비현실적이며 쓸모가 없습니다. 속성의 요점은 getter 또는 setter와 같은 시간이 실제로 필요할 때까지 공용 속성을 자유롭게 사용할 수 있도록하는 것입니다. 그런 다음 클라이언트 코드를 손상시키지 않고 public 속성을 속성으로 바꿉니다.
Luciano Ramalho 2016 년

9
class MyException(Exception):

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

e = MyException('asdf')
print e

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


1
이전 예외 클래스는 여러 인수를 사용합니다. 메시지 속성을 수행하는 것과 같은 것을 완전히 피할 수 있지만 기존 코드가 손상되면 자체 메시지 속성을 구현하여 문제를 해결할 수 있습니다.
Sahas

8

경고를 복제하는 방법

질문의 샘플 코드로 이것을 복제 할 수 없으므로 문제를 분명히 해 보겠습니다. 경고를 켜면 ( -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'

이 답변도 참조하십시오.

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


4

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

class MyException(Exception):

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

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

나에게 해킹처럼 보인다.

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


4

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

1
예, 너무 생각하지 마십시오. str(my)대신에 사용하십시오 my.message.
Christian Long

1

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'δσφφδσ')) 

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


1

pzrq의 게시물은 다음을 사용한다고 말합니다.

str(e)

이것이 바로 내가 필요한 것입니다.

(유니 코드 환경에있는 경우 다음과 같이 나타납니다.

unicode(e)

작동하며 유니 코드가 아닌 환경에서 제대로 작동하는 것으로 보입니다)

Pzrq는 다른 좋은 것들을 많이 말했지만 모든 좋은 것들 때문에 답변을 거의 놓쳤습니다. 50 점이 없기 때문에 간단한 해결책에주의를 기울이려는 답변에 대해 언급 할 수 없으며 15가 없으므로 답변을 투표 할 수는 없지만 게시 할 수는 있습니다 (뒤로 느낀다. 오 잘)-그래서 여기에 게시하고 있습니다-아마도 그 점을 잃을 것입니다 ...

내 요점은 pzrq의 답변에주의를 기울이는 것이기 때문에 아래의 모든 부분에서 눈 부시지 말고 놓치지 마십시오. 이 게시물의 처음 몇 줄이 가장 중요합니다.

내 이야기:

내가 여기에 왔던 문제는 당신이 통제 할 수없는 클래스에서 예외를 잡으려는 경우였습니다. 가능한 모든 예외에서 메시지를 얻을 수 있도록 코드에서 사용하는 모든 가능한 클래스를 서브 클래스 화하지 않을 것입니다!

나는 사용하고 있었다 :

except Exception as e:
   print '%s (%s)' % (e.message,type(e))

우리 모두가 알고 있듯이 OP가 여기에 왔던 경고에 대해 경고합니다.

except Exception as e:
   print '%s (%s)' % (str(e),type(e))

하지 않았다.

나는 유니 코드 환경에 있지 않지만 jjc의 답변으로 궁금해 졌으므로 시도해야했습니다. 이러한 맥락에서 이것은 다음과 같이됩니다.

except Exception as e:
   print '%s (%s)' % (unicode(e),type(e))

놀랍게도 str (e)과 똑같이 작동 했으므로 이제는 내가 사용하고 있습니다.

'str (e) / unicode (e)'가 '승인 된 파이썬 방식'인지 여부를 알 수 없으며 3.0에 도달했을 때 왜 그것이 좋지 않은지 알아볼 것입니다. 예상치 못한 예외 (*)는 죽지 않고 여전히 정보를 얻지 못합니다.

(*) 흠. "예기치 않은 예외"-방금 말더듬 한 것 같습니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.