1行で複数の例外をキャッチ(ブロックを除く)


2757

私ができることを知っています:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

私もこれを行うことができます:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

しかし、私が2つの異なる例外の中で同じことをしたい場合、私が今考えることができる最善はこれを行うことです:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

私がこのようなことをすることができる方法はありますか(両方の例外で行うアクションはであるためですsay please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

次の構文と一致するため、これは実際には機能しません。

try:
    # do something that may fail
except Exception, e:
    # say please

したがって、2つの異なる例外をキャッチするための私の努力は、正確には実行されません。

これを行う方法はありますか?


6
Python 3では、後者はもはや有効な構文ではないことに注意してください。
gerrit

回答:


3724

Pythonのドキュメントから:

except節は、括弧で囲まれたタプルとして複数の例外を指定するかもしれません、例えば

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

または、Python 2のみ:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

例外と変数をコンマで区切ることは、Python 2.6および2.7では引き続き機能しますが、現在は非推奨であり、Python 3では機能しません。今、あなたは使用すべきasです。


9
私はそれを試してみました... list、それはTypeErrortupleキャッチが期待どおりに機能するには、エラーがに含まれている必要があります。
BallpointBen 2018年

4
この場合、タプルが必要であることが文書化されていることがはっきりとわかるのに、なぜリストを使用したことがあるのでしょうか。
Mechanical_Meat

6
「かっこで囲まれたタプル」が単に構文上のものなのか、それとも真正なタプルが必要なのかは不明でした。他の場所で括弧なしのタプルを作成し、それをexcept行で使用する可能性があるため、「Parenthesized」は誤解を招く可能性があります。except行で作成された場合のみ、必ず括弧で囲まれます。
BallpointBen 2018年

5
@JosephBani、ジェネレータ式はどうですか?
jammertheprogrammer

12
@JosephBaniそれはまったく真実ではありません。では2 + (x * 2)(x * 2)確かにタプルではありません。括弧は一般的なグループ化構文です。タプルの特徴的な特徴は、コンマが含まれていることです-Pythonのドキュメントを参照しください。
Soren Bjornstad

314

1行で複数の例外をキャッチするにはどうすればよいですか(ブロックを除く)

これを行う:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

括弧は、コンマを使用してエラーオブジェクトを名前に割り当てる古い構文のために必要です。asキーワードは、割り当てに使用されます。エラーオブジェクトには任意の名前を使用できますが、error個人的に好みます。

ベストプラクティス

現在、Pythonと互換性のある方法でこれを行うには、例外をコンマで区切り、括弧で囲むことで、例外タイプをたどることで例外インスタンスを変数名に割り当てた以前の構文と区別し、コンマ。

簡単な使用例を次に示します。

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

バグの非表示を回避するために、これらの例外のみを指定しています。バグが発生した場合は、完全なスタックトレースを期待しています。

これはここに文書化されています:https : //docs.python.org/tutorial/errors.html

例外を変数に割り当てることができます(e一般的ですが、長い例外処理がある場合、またはIDEが私のようにそれよりも大きい選択のみをハイライトする場合は、より詳細な変数を使用することをお勧めします。)インスタンスにはargs属性があります。次に例を示します。

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

Python 3ではerrexceptブロックが終了するとオブジェクトがスコープ外になることに注意してください。

非推奨

エラーをコンマで割り当てるコードが表示される場合があります。この使用法は、Python 2.5以前で使用できる唯一の形式であり、廃止予定です。コードをPython 3で上位互換にしたい場合は、新しい形式を使用するように構文を更新する必要があります。

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

コードベースにコンマ名の割り当てがあり、Python 2.5以降を使用している場合は、新しい方法に切り替えて、アップグレード時にコードの互換性を維持します。

suppressコンテキストマネージャ

受け入れられた答えは、実際には最低4行のコードです。

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

tryexceptpassラインが有する一列に取り扱うことができるのPython 3.4で利用できる抑制コンテキストマネージャ、

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

したがって、pass特定の例外については、を使用してくださいsuppress


2
を追加するとsuppress、単に実行passするよりもはるかに読みやすくなりますexcept
Mache

50

Pythonのドキュメントから-> 8.3例外の処理

try声明は異なる例外のハンドラを指定するには、より多くの句を除いて1よりも持っていることがあります。最大で1つのハンドラが実行されます。ハンドラーは、対応するtry節で発生する例外のみを処理し、同じtryステートメントの他のハンドラーでは処理しません。except節は、括弧で囲まれたタプルとして複数の例外を指定するかもしれません、例えば:

except (RuntimeError, TypeError, NameError):
    pass

このタプルを括弧で囲む必要があることに注意してください。これValueError, e:except ValueError as e:、最近のPythonで通常記述される構文(以下で説明)に使用される構文を除いたためです。古い構文は、下位互換性のために引き続きサポートされています。これは、あなたが望むものとexcept RuntimeError, TypeError同等 ではありませんexcept (RuntimeError, TypeError):が、except RuntimeError as TypeError:どちらが望ましいものではないことを意味します。


35

多数の例外を頻繁に使用する場合は、タプルを事前定義できるため、何度も再入力する必要がありません。

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

ノート:

  1. また、事前定義されたタプル以外の例外をキャッチする必要がある場合は、別のexceptブロックを定義する必要があります。

  2. グローバル変数を許容できない場合は、それをmain()で定義し、必要な場所に渡します...


17

これを行う方法の1つは、

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

もう1つの方法は、exceptブロックによって実行されるタスクを実行するメソッドを作成exceptし、書き込むすべてのブロックを通じてそれを呼び出すことです。

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

2つ目はこれを行うための最良の方法ではないことを知っていますが、これを行うためのいくつかの方法を示しています。


2つ目の例外を使用しているのは、それぞれに異なる処理が必要な2つの例外があるためです。そのようにそれを行うことで何か問題がありますか?
majikman

@majikman同じ関数を呼び出す複数の句を持つ2番目の方法は、2つの例外に対して同じことを繰り返さないようにする場合に最適ではありません。(正しい方法については、他の回答を参照してください)。ただし、except例外を別の方法で処理する場合は、複数の句を使用するのが普通です。
町の名を冠した
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.