例外のキャッチについて


696

すべての例外をキャッチするtry/ exceptブロックをどのように書くことができますか?


4
ほとんどの場合、おそらく、例外をキャッチしようとすると、smthが間違っていることになります。つまり、コード内の何かのスペルを間違えるだけで、それを知らないことさえあります。特定の例外をキャッチすることをお勧めします。
vwvolodya 2014

12
より正確には、起こり得るすべての例外をキャッチすることは、それらがサイレントにキャッチされた場合にのみ問題になります。キャッチされたエラーメッセージが出力されsys.stderr、場合によってはログに記録される場所以外に、このアプローチが適切な場所を考えるのは困難です。これは完全に有効で一般的な例外です。
Evgeni Sergeev 2016年

試しましたtry: whatever() except Exception as e: exp_capture() か?
チャーリーパーカー

回答:


564

あなたはできますが、おそらくすべきではありません:

try:
    do_something()
except:
    print "Caught it!"

ただし、これはのような例外もキャッチKeyboardInterruptし、通常はそれを望まないでしょうか。すぐに例外を再発生させない限り、ドキュメントの次の例参照してください。

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise


15
最後のステートメントは真実ではありませんexcept Exception:。BaseExceptionのものもキャッチする場合を除いて、明示的にベアを言う必要があります。
ピクラー、2013

7
本当にstderrに出力する必要があります。
nyuszika7h 2015年

41
私は「すべきではない」という発言に非常に強く反対します。慎重に行う必要があります。例外で完全に狂ってしまい、それらをすべて追跡するサードパーティのライブラリ(時には動的にロードされる!!)を扱っている場合、非常に苦痛な作業になる可能性があります。お使いのシステムに大きな痛みを伴うバグ。とはいえ、できる限り多くを追跡して適切に処理し、見逃したものはすべてバックアップでキャッチすることをお勧めします。
Blaze、

26
また、インスタンス変数を宣言していないダックタイピング言語では、突然、すべての例外を入力しないことが非常に心配になります。うーん!
Blaze

834

except:(他の人があなたが使うべきではないと言っているように)裸の節を除いて、あなたは単にキャッチすることができますException

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

通常、これをコードの最外部レベルで行うことを検討するのは、たとえば、終了する前にキャッチされていない例外を処理したい場合だけです。

利点except Exception裸の上にはexcept、ほとんど明らかに、それはキャッチ文句を言わないことをいくつかの例外があるということですKeyboardInterruptSystemExit:あなたがキャッチし、それらを飲み込んだ場合、あなたはあなたのスクリプトを終了するには、誰のために懸命にそれを作ることができます。


私は同じことを考えていましたが、それらは不利です。一度キャッチされると2つのエラーが発生し、印刷している場合を除いて、tryブロックから抜け出し、2番目のエラーが発生することはありません。 。

6
不思議に思う人にとっては、完全に私の期待に反して、これは少なくともpython 2.xでは、intのような例外ではないサブクラス化されたものをキャッチします。
Joseph Garvin、2014年

5
@JosephGarvin、それは正しくありませんException。つまり、これはサブクラス化されない「例外以外」をキャッチしません。をint例外として発生させることは不可能であり、そうしようとすると例外が発生することに注意してくださいTypeError。これはexcept Exception、そのような場合に囲み句によってキャッチされるものです。一方、古いスタイルのクラスは、サブクラスを持たない「非例外」として発生および修飾できます。Exceptionこれ、裸のexcept句ではなくexcept Exception句でキャッチされます。
Yoel、2016年

4
@JosephGarvinがこのブログエントリを確認します。chris-lamb.co.uk/ posts / no-one-expects-string-literal-exceptionこれは@Yoel です。あなたのテストはちょうどマスクしましたTypeError
Duncan

2
@CharlieParkerは、それがあなたが望むものである場合、それらをキャッチすることで何も問題はありませんが、ほとんどの場合そうではありません。呼び出しsys.exit()は通常、アプリが終了することを期待しますが、SystemExitをキャッチしても終了しません。同様に、実行中のスクリプト(WindowsではCtrl-Break)でControl-Cを押すと、エラーをキャッチせずにプログラムが停止することが期待されます。ただし、既存の前にクリーンアップを実行する場合は、これらのいずれかまたは両方をキャッチできます。
ダンカン

100

これを行うと、一般的な例外を処理できます

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message

8
すべての例外の基本クラスがBaseExceptionであり、Exceptionクラスファミリーに含まれていない製品コードに遭遇したため、これはすべての例外をキャッチしない可能性があります。詳細については、docs.python.org / 3 / library /…を参照してください。
Dデイ

4
これはすべての例外をキャッチするわけではありません。
Andy_A̷n̷d̷y̷

6
技術的には、システム終了しないすべての例外をキャッチする必要があります。docs @DDayのリンクから:「exception BaseException:すべての組み込み例外の基本クラス。ユーザー定義クラスによって直接継承されることを意図していません(そのためには、Exceptionを使用してください)。」これを無視するコードで作業している場合、またはシステム終了例外をキャッチする必要がある場合を除いて、上記は使用しても問題ありません。
Peter Cassetta

@PeterCassettaいつシステム終了例外をキャッチしたいですか?これらをキャッチしたくないという質問の一般的なスレッドのようですが、理由はわかりません。通常はどうしてですか?
チャーリーパーカー

68

起こり得るすべての例外をキャッチするには、catchしBaseExceptionます。例外階層の最上位にあります。

Python 3:https : //docs.python.org/3.5/library/exceptions.html#exception-hierarchy

Python 2.7:https : //docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

しかし、他の人が述べたように、通常、これは必要ではなく、特定の場合にのみ必要です。


1
Ctrl-Cを押した後に長時間実行されているジョブの進行状況を保存したいのは珍しいことですか?
BallpointBen 2018

54

ここにあるものと同様の非常に単純な例:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

すべての例外をキャッチしようとしている場合は、「print "例外をスローする可能性のあるアクションを実行しています。"」の代わりに、すべてのコードを「try:」ステートメント内に配置します。

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

上記の例では、次の順序で出力が表示されます。

1)例外をスローする可能性のあるアクションを実行する。

2)最後に、例外がスローされたかどうかに関係なく、tryステートメントを実行した直後に呼び出されます。

3)「例外がスローされました!」または「すべてが美しく見えます!」例外がスローされたかどうかによって異なります。

お役に立てれば!


26

これを行うには、特にPython 3.0以降で複数の方法があります。

アプローチ1

これは単純なアプローチですが、実際にどのコード行が例外をスローしているか正確にわからないため、お勧めしません。

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

アプローチ2

この方法は、各例外の詳細を提供するため推奨されます。以下が含まれます:

  • コードの行番号
  • ファイル名
  • より詳細な方法での実際のエラー

唯一の欠点は、tracbackをインポートする必要があることです。

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()

21

Python 2.7で例外名があるかどうかをテストするためのこの小さなトリックを見つけました。コードで特定の例外を処理したことがあるので、その名前が処理された例外のリスト内にあるかどうかを確認するためのテストが必要でした。

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception

2
try:
    whatever()
except:
    # this will catch any exception or error

これは適切なPythonコーディングではないことに言及する価値があります。これは、キャッチしたくない多くのエラーもキャッチします。


他のいくつかの回答で言及されているように、すべての例外をキャッシュしないでください。この目的のためにBaseExceptionを使用する必要がありますが、あなたが言ったように、誰もこのようなすべての例外をキャッチするべきではありません。開発中を除いて、より細かく追加することを目標とする場合は、最初は大丈夫だと思いますが、そうではないと思います...
Pyglouthon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.