サーチ…


前書き

実行中に検出されたエラーは例外と呼ばれ、無条件に致命的ではありません。ほとんどの例外はプログラムによって処理されません。選択した例外を処理するプログラムを記述することができます。 Pythonには、例外や例外ロジックを扱う特定の機能があります。さらに、例外には豊富な型階層があり、すべてBaseException型を継承しています。

構文

  • 例外を提起する
  • raise#すでに発生している例外を再発生させる
  • 原因#Pythonから引き上げる3 - 例外の原因を設定する
  • 例外をNoneから出す#Python 3 - すべての例外コンテキストを抑止する
  • 試してください:
  • [ 識別子として] [例外タイプ]を除きます。
  • else:
  • 最後に:

例外の発生

コードが条件に遭遇した場合、不適切なパラメータなどの処理方法がわからない場合は、適切な例外が発生するはずです。

def even_the_odds(odds):
    if odds % 2 != 1:
        raise ValueError("Did not get an odd number")
    
    return odds + 1

例外のキャッチ

例外をキャッチするには、 try...except:を使用します。次のように、正確な例外を指定する必要があります。

try:
    x = 5 / 0
except ZeroDivisionError as e:
    # `e` is the exception object
    print("Got a divide by zero! The exception was:", e)
    # handle exceptional case
    x = 0  
finally:
    print "The END"
    # it runs no matter what execute.

指定された例外クラス(この場合はZeroDivisionErrorは、そのクラスまたはその例外のサブクラスであるすべての例外をキャッチします。

たとえば、 ZeroDivisionErrorArithmeticErrorサブクラスです。

>>> ZeroDivisionError.__bases__
(<class 'ArithmeticError'>,)

したがって、次のZeroDivisionErrorます:

try:
    5 / 0
except ArithmeticError:
    print("Got arithmetic error")

最終的にクリーンアップコードを実行する

場合によっては、何らかのリソースがクリーンアップされなければならないなど、例外が発生した場合でも、発生するものが必要な場合があります。

try節のfinallyブロックは、例外が発生したかどうかにかかわらず発生します。

resource = allocate_some_expensive_resource()
try:
    do_stuff(resource)
except SomeException as e:
    log_error(e)
    raise  # re-raise the error
finally:
    free_expensive_resource(resource)

このパターンは、( withステートメントを使用with )コンテキストマネージャーでよく扱われることがよくあります。

例外の再発生

場合によっては、例えばログを採取するために、検査するために例外をキャッチすることがあります。検査の後、前と同じように例外が伝搬し続けるようにします。

この場合、引数なしでraise文を使用するだけです。

try:
    5 / 0
except ZeroDivisionError:
    print("Got an error")
    raise

ただし、呼び出し元スタックの上位のユーザーが例外をキャッチして何とか処理できることに注意してください。完成した出力は、いずれの場合にも発生するため、この場合は迷惑になる可能性があります(キャッチまたはキャッチされません)。だから、元の例外と同様に状況についてのあなたのコメントを含む別の例外を発生させる方が良いかもしれません:

try:
    5 / 0
except ZeroDivisionError as e:
    raise ZeroDivisionError("Got an error", e)

しかしこれには、例外トレースを正確にこのraiseに減らすという欠点があり、引数なしのraiseは元の例外トレースを保持します。

Python 3では、 raise - from構文を使って元のスタックを保持することができます:

    raise ZeroDivisionError("Got an error") from e

発生元のチェーン例外

例外を処理するプロセスでは、別の例外を発生させることができます。たとえば、ファイルから読み込み中にIOErrorが発生した場合、アプリケーション固有のエラーを発生させて、ライブラリのユーザーに提示することができます。

Python 3.x 3.0

例外処理をどのように処理したかを示すために、例外を連結することができます。

>>> try:
    5 / 0
except ZeroDivisionError as e:
    raise ValueError("Division failed") from e

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ValueError: Division failed

例外階層

例外処理は、例外クラスの継承構造によって決定される例外階層に基づいて行われます。

たとえば、 IOErrorOSErrorは両方ともEnvironmentErrorサブクラスです。 IOErrorを捕捉するOSErrorOSError捕捉しません。ただし、 EnvironmentErrorを捕捉するコードは、 IOErrorOSErrorの両方を捕捉しIOError

組み込み例外の階層:

Python 2.x 2.3
BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
       +-- ImportWarning
       +-- UnicodeWarning
       +-- BytesWarning
Python 3.x 3.0
BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

例外もオブジェクトです

例外は、組み込みのBaseExceptionを継承する単なる通常のPythonオブジェクトです。 Pythonスクリプトはraise文を使用して実行を中断することができ、Pythonはその時点で呼び出しスタックのスタックトレースと例外インスタンスの表現を出力します。例えば:

>>> def failing_function():
...     raise ValueError('Example error!')
>>> failing_function()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in failing_function
ValueError: Example error!

'Example error!'というメッセージを含むValueError'Example error!'私たちのfailing_function()によってfailing_function()れました。これはインタープリタで実行されました。

コーリングコードは、コールが発生させることができるすべてのタイプの例外を処理することを選択できます。

>>> try:
...     failing_function()
... except ValueError:
...     print('Handled the error')
Handled the error

例外処理コードのexcept...部分に例外オブジェクトを割り当てることによって、例外オブジェクトを保持することができます。

>>> try:
...     failing_function()
... except ValueError as e:
...     print('Caught exception', repr(e))
Caught exception ValueError('Example error!',)

組み込みのPython例外の完全なリストとその説明は、Pythonドキュメント( https://docs.python.org/3.5/library/exceptions.html)にあります 。そして、ここでは階層構造で配列された完全なリストがあります: Exception Hierarchy

カスタム例外の種類を作成する

Exceptionから継承するクラスを作成する:

class FooException(Exception):
    pass
try:
    raise FooException("insert description here")
except FooException:
    print("A FooException was raised.")

または別の例外タイプ

class NegativeError(ValueError):
      pass

def foo(x):
    # function that only accepts positive values of x
    if x < 0:
        raise NegativeError("Cannot process negative numbers")
    ...  # rest of function body
try:
    result = foo(int(input("Enter a positive integer: ")))  # raw_input in Python 2.x
except NegativeError:
    print("You entered a negative number!")
else:
    print("The result was " + str(result))

すべてをキャッチしないでください!

それはしばしばすべてのExceptionをキャッチするために魅力Exceptionですが、

try:
    very_difficult_function()
except Exception:
    # log / try to reconnect / exit gratiously
finally:
    print "The END"
    # it runs no matter what execute.

あるいは、すべて( BaseExceptionExceptionを含むすべての子を含む):

try:
    even_more_difficult_function()
except:
    pass  # do whatever needed

ほとんどの場合、それは悪い習慣です。 SystemExitKeyboardInterruptMemoryErrorなど、意図した以上のものを捕まえる可能性があります。通常は、通常のシステムエラーやロジックエラーとは異なる処理が行われます。また、内部コードが間違っている可能性があり、その状態から適切に回復する方法について明確な理解がないことを意味します。あなたがすべてのエラーをキャッチしている場合は、どのようなエラーが発生したのか、それを修正する方法はわかりません。

これはより一般的に「バグマスキング」と呼ばれ、避けるべきです。黙って失敗するか、悪化するのではなく、プログラムをクラッシュさせ、より深い実行レベルで失敗するようにしてください。 (それがトランザクションシステムであると想像してください)

通常、これらの構造体はプログラムの非常に外側のレベルで使用され、バグを修正できるようにエラーの詳細を記録するか、エラーをより具体的に扱うことができます。

複数の例外をキャッチする

複数の例外キャッチする方法はいくつかあります。

1つは、同じ方法でキャッチして処理する例外タイプのタプルを作成することです。この例では、コードでKeyError例外とAttributeError例外が無視されます。

try:
    d = {}
    a = d[1]
    b = d.non_existing_field
except (KeyError, AttributeError) as e:
    print("A KeyError or an AttributeError exception has been caught.")

異なる例外をさまざまな方法で処理したい場合は、各タイプごとに別々の例外ブロックを用意することができます。この例では、引き続きKeyErrorAttributeErrorキャッチしKeyErrorが、例外をさまざまな方法で処理します。

try:
    d = {}
    a = d[1]
    b = d.non_existing_field
except KeyError as e:
    print("A KeyError has occurred. Exception message:", e)
except AttributeError as e:
    print("An AttributeError has occurred. Exception message:", e)

例外処理の具体例

ユーザー入力

ユーザーが入力を介して番号をinput 。入力が数字であることを確認する必要があります。 try / exceptを使用することができます:

Python 3.x 3.0
while True:
    try:
        nb = int(input('Enter a number: '))
        break
    except ValueError:
        print('This is not a number, try again.')

注:Python 2.xは代わりにraw_inputを使用します。関数inputはPython 2.xでは存在しinputが、セマンティクスは異なります。上記の例では、 input2 + 2ような式を受け取り、数値に評価されます。

入力を整数に変換できないValueErrorは、 ValueErrorが発生します。あなたはでそれをキャッチすることができますexcept 。例外が発生しなければ、 breakはループから飛び出します。ループの後、 nbは整数を含む。

辞書

range(n)ような連続した整数のリストを反復しているとし、特定の整数に遭遇したときに行うべきことに関する情報が入っている辞書dリストを持っているとしたらd[i]スキップします

d = [{7: 3}, {25: 9}, {38: 5}]

for i in range(len(d)):
    do_stuff(i)
    try:
       dic = d[i]
       i += dic[i]
    except KeyError:
       i += 1

存在しないキーの辞書から値を取得しようとすると、 KeyErrorが発生します。

その他

elseブロックのコードは、 tryブロック内のコードによって例外が発生していない場合にのみ実行されます。これは、例外がスローされた場合に実行したくないコードがいくつかあるが、そのコードによってスローされた例外を捕まえたくない場合に便利です。

例えば:

try:
    data = {1: 'one', 2: 'two'}
    print(data[1])
except KeyError as e:
    print('key not found')
else:
    raise ValueError()
# Output: one
# Output: ValueError

この種のelse: elif else節を開始するifは、と組み合わせることはできません。下にインデントされている必要がある場合は、次のifelse:

try:
    ...
except ...:
    ...
else:
    if ...:
        ...
    elif ...:
        ...
    else:
        ...


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow