Pythonで例外を発生させ、後でexcept
ブロックを介して捕捉できるようにするにはどうすればよいですか。
Pythonで例外を手動でスロー/発生させるにはどうすればよいですか?
問題に意味的に適合する最も具体的な例外コンストラクターを使用 。
メッセージに具体的に記入してください、例:
raise ValueError('A very specific bad thing happened.')
一般的な例外を発生させないでください。それをキャッチするには、それをサブクラス化する他のすべてのより具体的な例外をキャッチする必要があります。
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
ステートメント代わりに、問題に意味的に適合する最も具体的な例外コンストラクターを使用します 。
raise ValueError('A very specific bad thing happened')
また、コンストラクタに任意の数の引数を渡すこともできます:
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
これらの引数は、Exceptionオブジェクトのargs
属性によってアクセスされます。例えば:
try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
プリント
('message', 'foo', 'bar', 'baz')
Python 2.5では、例外をサブクラス化し、message
の使用を停止することをユーザーに推奨するために、実際のargs
属性がBaseExceptionに追加されましたが、 message
およびargsの元の廃止は撤回されました 。
except
句Except節内では、たとえば、特定のタイプのエラーが発生したことをログに記録してから、再度発生させることができます。スタックトレースを保持しながらこれを行う最良の方法は、bare 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]
必要に応じて、新しいレイズで何が起こるかを変更できます。インスタンスに新しい引数を設定する:
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 :
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.
すべての最新バージョンでは、BaseException型を発生させていないため、これは実際にTypeErrorを発生させます。適切な例外をチェックしておらず、問題を認識しているレビュアーがいない場合、プロダクションに入る可能性があります。
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.')
これをしないでください 。裸の
Exception
を上げることは絶対に ではありません 正しいことです。 Aaron Hallのすばらしい答えを参照してください 代わりに。
これ以上のPythonicを手に入れることはできません。
raise Exception("I know python!")
詳細については、 raise文のdocs pythonを参照してください。
予期しない状況に対応して例外をスローする必要があり、決してキャッチするつもりはないのですが、発生した場合にそこからデバッグできるようにするために単に速く失敗するという最も一般的なケース - AssertionError
:
if 0 < distance <= RADIUS:
#Do something.
Elif RADIUS < distance:
#Do something.
else:
raise AssertionError("Unexpected value of 'distance'!", distance)
Python 3では、例外を発生させるための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
Exceptionを発生させます。
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から例外(args)を発生させる
次の例に示すように、このステートメントは、別の例外に応答して発生した例外に元の例外の詳細を含めることができる例外チェーンを作成するために使用されます。
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
既存の回答を先に読んでください。これは単なる補足です。
引数があってもなくても例外を発生させることができることに注意してください。
例:
raise SystemExit
プログラムを終了しますが、何が起こったのか知りたいと思うかもしれません。あなたはこれを使うことができます。
raise SystemExit("program exited")
これはプログラムを閉じる前に "program exited"をstderrに出力します。
例外をスローするもう1つの方法は assert
です。もしそうでなければAssertionError
を発生させるであろうならば、あなたは条件が満たされていることを検証するためにassertを使うことができます。詳細は こちら をご覧ください。
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))
注意してください:一般的な例外を処理したいことがあります。大量のファイルを処理してエラーを記録している場合は、ファイルに発生したエラーを検出して記録し、残りのファイルの処理を続けることをお勧めします。その場合、try except Exception:
ブロックはそれを実行するための良い方法です。あなたはまだraise
特定の例外をしたいと思うでしょう。