183

次のユーザー定義の例外を使用すると、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

これの何が問題なのですか?非推奨の警告を取り除くには、何を変更する必要がありますか?

4

8 に答える 8

160

解決策-コーディングはほとんど必要ありません

から例外クラスを継承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以降)では、( Python 2.5以降で)BaseExceptionから継承するExceptionからカスタム例外クラスを継承することになっています。背景については、PEP352で詳しく説明されています。

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__(メッセージとして使用できる)引数が1つしかない場合は、すでに意味のある方法で実装されています。

他の人が提案したように、繰り返し__str__たり、__init__実装したり、作成したりする必要はありません。_get_message

于 2011-05-17T10:58:34.530 に答える
10

警告を再現する方法

質問のサンプル コードでこれを再現できないため、問題を明確にさせてください。( -WflagPYTHONWARNINGS環境変数、またはwarnings モジュールを使用して)警告をオンにしている場合、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、Python 設計者が意図したように、組み込み例外をサブクラス化することです。

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

Exception への 1 つの引数 (メッセージ) があり、それが必要であることがわかっている場合は、メッセージ属性を避けてstrエラーの を取得することをお勧めします。サブクラス化された について言うException

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

そして使用法:

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

この回答も参照してください。

最新のPythonでカスタム例外を宣言する適切な方法は?

于 2015-01-29T23:06:04.337 に答える
4

geekQ's answerから続けて、推奨されるコードの置き換えは、何をする必要があるかによって異なります。

### 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
于 2015-06-17T02:32:20.650 に答える
4

私が知る限り、メッセージ属性に別の名前を使用するだけで、基本クラスとの競合が回避され、非推奨の警告が停止します。

class MyException(Exception):

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

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

私にはハックのようです。

サブクラスがメッセージ属性を明示的に定義している場合でも、警告が発行される理由を誰かが説明できるかもしれません。基本クラスにこの属性がなくなった場合、問題はないはずです。

于 2010-10-13T23:00:36.227 に答える