回答:
Pythonで例外を手動でスロー/発生させるにはどうすればよいですか?
問題に意味的に適合する最も具体的なExceptionコンストラクターを使用します。
メッセージは具体的に記述してください。例:
raise ValueError('A very specific bad thing happened.')
ジェネリックを上げないでくださいException
。それをキャッチするには、それをサブクラス化する他のより具体的な例外をすべてキャッチする必要があります。
raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.
例えば:
def demo_bad_catch():
try:
raise ValueError('Represents a hidden bug, do not catch this')
raise Exception('This is the exception you expect to handle')
except Exception as error:
print('Caught this error: ' + repr(error))
>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)
そして、より具体的なキャッチは一般的な例外をキャッチしません:
def demo_no_catch():
try:
raise Exception('general exceptions not caught by specific handling')
except ValueError as e:
print('we will not catch exception: Exception')
>>> demo_no_catch()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling
raise
ステートメント代わりに、問題に意味的に適合する最も具体的なExceptionコンストラクタを使用してください。
raise ValueError('A very specific bad thing happened')
また、コンストラクタに任意の数の引数を渡すことができます。
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
これらの引数はargs
、Exception
オブジェクトの属性によってアクセスされます。例えば:
try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
プリント
('message', 'foo', 'bar', 'baz')
Python 2.5では、ユーザーにExceptionsのサブクラスを作成してを使用しないように促すmessage
ためBaseException
に実際の属性が追加されましたargs
が、message
argsの導入と元の非推奨は撤回されました。
except
句except句の内部では、たとえば、特定のタイプのエラーが発生したことをログに記録してから、再度発生させることができます。スタックトレースを保持しながらこれを行う最良の方法は、最小限のraiseステートメントを使用することです。例えば:
logger = logging.getLogger(__name__)
try:
do_something_in_app_that_breaks_easily()
except AppError as error:
logger.error(error)
raise # just this!
# raise AppError # Don't do this, you'll lose the stack trace!
スタックトレース(およびエラー値)をsys.exc_info()
で保持できますが、これはエラーが発生しやすく、Python 2と3の間の互換性の問題があるため、ベアraise
を使用して再レイズすることをお勧めします。
説明すると、sys.exc_info()
はタイプ、値、およびトレースバックを返します。
type, value, traceback = sys.exc_info()
これはPython 2の構文です-これはPython 3と互換性がないことに注意してください。
raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
必要に応じて、新しいレイズで何が起こるかを変更できます。たとえばargs
、インスタンスにnew を設定します。
def error():
raise ValueError('oops!')
def catch_error_modify_message():
try:
error()
except ValueError:
error_type, error_instance, traceback = sys.exc_info()
error_instance.args = (error_instance.args[0] + ' <modification>',)
raise error_type, error_instance, traceback
引数を変更する間、トレースバック全体を保存しました。これはベストプラクティスではなく、 Python 3の無効な構文であることに注意してください(互換性の維持を回避するのがはるかに困難になります)。
>>> catch_error_modify_message()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in catch_error_modify_message
File "<stdin>", line 2, in error
ValueError: oops! <modification>
ではPythonの3:
raise error.with_traceback(sys.exc_info()[2])
この場合も、手動でトレースバックを操作することは避けてください。それはだあまり効率的で、よりエラーが発生しやすいです。また、スレッドを使用しsys.exc_info
ていて、誤ったトレースバックが発生する可能性がある場合(特に、制御フローに例外処理を使用している場合-私は個人的には避けがちです)。
Python 3では、トレースバックを保持する例外をチェーンできます。
raise RuntimeError('specific message') from error
注意してください:
これらは簡単に非表示にでき、製品コードに侵入することもできます。例外を発生させたい場合、それらを実行すると例外が発生しますが、意図したものは発生しません!
Python 2では有効ですが、Python 3では無効です。
raise ValueError, 'message' # Don't do this, it's deprecated!
Pythonのはるかに古いバージョン(2.4以下)でのみ有効であり、文字列を発生させる人がいる場合があります。
raise 'message' # really really wrong. don't do this.
すべての最新バージョンではTypeError
、BaseException
型を発生させないため、これは実際にはを発生させます。適切な例外をチェックしておらず、問題を認識しているレビュー担当者がいない場合、本番環境に入る可能性があります。
例外を発生させて、APIを間違って使用している場合に、APIの消費者に警告します。
def api_func(foo):
'''foo should be either 'baz' or 'bar'. returns something very useful.'''
if foo not in _ALLOWED_ARGS:
raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))
「わざとエラーを出して、それが例外になるようにしたい」
独自のエラータイプを作成できます。アプリケーションに何か特定の問題があることを示したい場合は、例外階層の適切なポイントをサブクラス化するだけです。
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
および使用法:
if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')
raise sys.exc_info()[0], (sys.exc_info()[1], my_extra_info), sys.exc_info()[2]
私がしたいことをしているようで、私はそれで問題に遭遇したことがありません。しかし、それはハックに感じられ、受け入れられた慣習ではありません。もっと良い方法はありますか?
Exception
、親クラスとして派生しない4つの例外の1つを使用してはならないことを意味します。より具体的なサブクラスを作成できます。
AppError
例外を使用しています。組み込みのエラーのように使用する方が良いかもしれAttributeError
これをしないでください。裸を上げると
Exception
、絶対にありません行うには正しいこと。代わりにアーロンホールの優れた答えをご覧ください。
これより多くのpythonicを取得することはできません:
raise Exception("I know python!")
詳細については、Pythonのレイズステートメントのドキュメントをご覧ください。
Python3には、例外を発生させるための4つの異なる構文があります。
1. raise exception
2. raise exception (args)
3. raise
4. raise exception (args) from original_exception
1.例外を発生させるか2.例外を発生させる(引数)
を使用raise exception (args)
して例外を発生 args
させた場合、以下の例に示すように、例外オブジェクトを印刷するときにが印刷されます。
#raise exception (args)
try:
raise ValueError("I have raised an Exception")
except ValueError as exp:
print ("Error", exp) # Output -> Error I have raised an Exception
#raise execption
try:
raise ValueError
except ValueError as exp:
print ("Error", exp) # Output -> Error
3.上げる
raise
引数のないステートメントは、最後の例外を再評価します。これは、例外をキャッチした後に何らかのアクションを実行する必要があり、それを再度発生させたい場合に役立ちます。しかし、以前に例外がなかった場合、raise
ステートメントはTypeError
例外を発生させ ます。
def somefunction():
print("some cleaning")
a=10
b=0
result=None
try:
result=a/b
print(result)
except Exception: #Output ->
somefunction() #some cleaning
raise #Traceback (most recent call last):
#File "python", line 8, in <module>
#ZeroDivisionError: division by zero
4. original_exceptionから例外(引数)を発生させる
このステートメントは、次の例に示すように、別の例外に応答して発生する例外に元の例外の詳細を含めることができる例外チェーンを作成するために使用されます。
class MyCustomException(Exception):
pass
a=10
b=0
reuslt=None
try:
try:
result=a/b
except ZeroDivisionError as exp:
print("ZeroDivisionError -- ",exp)
raise MyCustomException("Zero Division ") from exp
except MyCustomException as exp:
print("MyException",exp)
print(exp.__cause__)
出力:
ZeroDivisionError -- division by zero
MyException Zero Division
division by zero
exception(args)
することに注意してくださいexception (args)
raise exception(args) from None
、現在アクティブな例外が処理され、関心がなくなったとも言えます。あなたが内部で例外を発生させる場合にはそうでない場合はexcept
ブロックし、それが処理されない、両方の例外のトレースバックがメッセージで区切ら表示されます「上記の例外の取り扱い時には、別の例外が発生しました」
予期しない状況に対応して例外をスローする必要があり、キャッチするつもりはないが、単に失敗して、発生した場合にそこからデバッグできるようにするという一般的なケースでは、最も論理的なケースはAssertionError
:
if 0 < distance <= RADIUS:
#Do something.
elif RADIUS < distance:
#Do something.
else:
raise AssertionError("Unexpected value of 'distance'!", distance)
ValueError
よりも良いケースAssertionError
です。問題は値にあります。この場合に本当に必要なAssertionError
場合は、と書いてくださいassert distance > 0, 'Distance must be positive'
。ただし、アサーションをオフにできるので(python -O
)、そのようにエラーチェックしないでください。
-O
。
まず既存の回答を読んでください。これは単なる補遺です。
引数の有無にかかわらず例外を発生させることができることに注意してください。
例:
raise SystemExit
プログラムを終了しますが、何が起こったのかを知りたい場合があるので、これを使用できます。
raise SystemExit("program exited")
これにより、プログラムを閉じる前に「プログラム終了」がstderrに出力されます。
raise SystemExit()
より良い選択ではないでしょうか?なぜ最初のものはうまくいくのですか?
例外をスローする別の方法はassert
です。アサートを使用して、条件が満たされていることを確認できますAssertionError
。満たされていない場合は、条件が発生します。詳細はこちらをご覧ください。
def avg(marks):
assert len(marks) != 0,"List is empty."
return sum(marks)/len(marks)
mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))
mark1 = []
print("Average of mark1:",avg(mark1))
あなたはそのためにPythonのレイズステートメントを学ぶべきです。これは、tryブロック内に保持する必要があります。例-
try:
raise TypeError #remove TypeError by any other error if you want
except TypeError:
print('TypeError raised')
raise
、私は、スタックトレースを壊すことなく、コード実行の複数のレベルでカスタムエラーのデバッグを実行できるようにするために必要なものです。