次のユーザー定義の例外を使用すると、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から)では、( 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__
は、特に1つの引数(メッセージとして使用できる)のみの場合に、意味のある方法で既に実装されています。
__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スタイルのクラスです。新しい例外は、任意の数の引数を取ります。
問題を明確にしましょう。質問のサンプルコードではこれを再現できないため、警告が有効になっている場合、Python 2.6および2.7で警告を再現します( -W
フラグ 、 PYTHONWARNINGS
環境変数、または 警告モジュール ):
>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'
.message
の使用をやめるエラータイプの名前、メッセージのレプリケート(ある場合)、および残りの引数のレプリケートを含む文字列を返すrepr(error)
を好みます。
>>> repr(error)
"Exception('foobarbaz',)"
.message
の使用中に警告を削除そして、DeprecationWarning
のridを取得する方法は、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
属性のみを取得する例外に対するメッセージが1つだけあり、それが必要な場合は、メッセージ属性を避けて、エラーのstr
を取得することをお勧めします。サブクラス化されたException
の場合:
class MyException(Exception):
'''demo straight subclass'''
そして使用法:
>>> myexception = MyException('my message')
>>> str(myexception)
'my message'
この回答も参照してください:
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
私が知る限り、メッセージ属性に異なる名前を使用するだけで、基本クラスとの競合が回避されるため、非推奨の警告が停止します。
class MyException(Exception):
def __init__(self, message):
self.msg = message
def __str__(self):
return repr(self.msg)
私にはハッキングのようです。
サブクラスがメッセージ属性を明示的に定義している場合でも、警告が発行される理由を誰かが説明できるかもしれません。基本クラスにこの属性がない場合、問題はないはずです。
pzrqの投稿は次のように使用するように言っています:
str(e)
これはまさに私が必要としていたものでした。
(ユニコード環境にいる場合、次のように表示されます:
unicode(e)
動作し、非ユニコード環境で正常に動作するようです)
Pzrqは他にも多くの良いものを言ったが、すべての良いもののために彼らの答えをほとんど逃した。私は50ポイントを持っていないので、彼らの答えにコメントして、うまくいく単純な解決策に注意を向けようとすることはできません。また、15ポイントを持っていないので、その答えを投票することはできませんが、投稿することはできますまあ)-だからここに投稿しています-たぶんそのためにポイントを失います...
私のポイントはpzrqの答えに注意を向けることであるので、下に目を通して見逃さないでください。この投稿の最初の数行が最も重要です。
私の物語:
私がここに来た問題は、あなたが制御できないクラスから例外をキャッチしたい場合でした-何ですか?考えられるすべての例外からメッセージを取得できるようにするために、コードが使用する可能性のあるすべてのクラスをサブクラス化するわけではありません。
私が使用していた:
except Exception as e:
print '%s (%s)' % (e.message,type(e))
私たち全員が知っているように、これはOPが尋ねた警告を与えます(これは私をここに連れてきました)、そしてこれ、それを行う方法としてpzrqが与えます:
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)」が「承認済みPython方法」であるかどうかはわかりません。3.0に到達したときになぜそれが良くないのかはおそらくわかるでしょうが、死ぬことなく予期しない例外(*)を処理し、それから情報を取得する機能がなくなることはありません...
(*) うーん。 「予期しない例外」-私はちょうどst音だと思います!
Str(myexception)を使用するようにアドバイスすると、python 2.7でUnicodeの問題が発生します。例:
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'δσφφδσ'))
期待どおりに動作し、エラー文字列の内容の一部にユーザー入力が含まれる場合に推奨されます