プログラムの実行中にエラーが発生した場合、エラーコードを返すことに事前に同意することで、エラーの有無とエラーの原因を知ることができます。オペレーティング システムが提供する呼び出しによってエラー コードが返されるのは非常に一般的です。たとえば、ファイルを開く関数 open() は、成功した場合はファイル記述子 (整数) を返し、エラーが発生した場合は -1 を返します。
エラーが発生したかどうかを示すためにエラー コードを使用するのは非常に不便です。関数自体が返す通常の結果がエラー コードと混合され、呼び出し元がエラーが発生したかどうかを判断するために大量のコードを使用することになるためです。 :
def bar():
r = foo()
r==(-1) の場合:
print 'エラー'
それ以外:
パス
高級言語には通常、try...excel...finally... というエラー処理メカニズムが組み込まれており、Python も例外ではありません。
試してください
例を使用して try のメカニズムを見てみましょう:
上記のコードは、10 / 0 を計算するときに除算エラーを生成します。
除数 0 を 2 に変更すると、実行結果は次のようになります。
また、さまざまなタイプのエラーが発生する場合、それらは別の else ステートメント ブロックで処理されるはずであると推測できます。そうです、さまざまなタイプのエラーをキャッチするために複数の例外が存在する可能性があります:
さらに、エラーが発生しない場合は、Except ステートメント ブロックの後に else ステートメントを追加できます。エラーが発生しない場合、else ステートメントは自動的に実行されます。
Python のすべてのエラーは BaseException クラスから派生します。一般的なエラーの種類と継承関係については、こちらを参照してください。
https://docs.python.org/2/library/Exceptions.html#Exception-hierarchy
エラーをキャッチするために try...以外を使用するもう 1 つの大きな利点は、関数 main() が foo() を呼び出し、foo() が bar() を呼び出すと、エラーが発生するということです。現時点では、 main() がそれをキャプチャしている限り、それを処理できます:
デフォルトバー:
foo(s) * 2
def main():
試してみてください:
bar('0')
StandardError を除く、e:
print 'エラー!'
最後に:
print 'ついに...'
コールスタック
エラーが捕捉されない場合は、エラーがスローされ、最終的に Python インタープリターによって捕捉され、エラー メッセージが出力されて、プログラムが終了します。 err.py を見てみましょう:
デフォルトバー:
foo(s) * 2
def main():
bar('0')
メイン()
エラーメッセージ行 1:
2 行目:
エラーが捕捉されなかった場合、Python インタプリタは当然エラー スタックを出力できますが、プログラムも終了します。エラーを捕捉できたので、エラー スタックを出力し、エラーの原因を分析し、同時にプログラムの実行を続行できます。 Python の組み込みログ モジュールは、エラー メッセージを簡単に記録できます: def foo(s): デフォルトバー: def main(): メイン() エラーがスローされます エラーはクラスであるため、エラーをキャッチすることはクラスのインスタンスをキャッチすることを意味します。したがって、エラーは何もないところから発生するのではなく、意図的に作成されてスローされます。 Python の組み込み関数はさまざまな種類のエラーをスローする可能性があり、自分で作成した関数もエラーをスローする可能性があります。 エラーをスローする場合は、まず必要に応じてエラー クラスを定義し、継承関係を選択してから、raise ステートメントを使用してエラー インスタンスをスローします。 def foo(s): 最後に、エラー処理の別の方法を見てみましょう: デフォルトバー: def main(): メイン() 実際、このエラー処理方法は無害であるだけでなく、非常に一般的でもあります。エラーをキャプチャする目的は、後の追跡のためにエラーを記録することだけです。ただし、現在の関数はエラーを処理する方法を知らないため、最も適切な方法はエラーをスローし続け、最上位の呼び出し元に処理させることです。 raise ステートメントがパラメータを取らない場合、現在のエラーは変更されずにスローされます。さらに、例外でエラーを発生させると、あるタイプのエラーを別のタイプに変換することもできます: 概要 Python の組み込みの try...excit...finally は、エラーを処理するのに非常に便利です。エラーが発生した場合、エラー メッセージを分析し、エラーが発生したコードの場所を特定することが最も重要です。 プログラムは積極的にエラーをスローし、呼び出し元に対応するエラーを処理させることもできます。ただし、どのエラーがスローされるか、およびそのエラーが発生する理由をドキュメントに明確に記載する必要があります。
# err.py
インポートログ
10 / int(s) を返します
foo(s) * 2
試してみてください:
bar('0')
StandardError を除く、e:
logging.Exception(e)
「終了」を印刷
同じエラーが発生しますが、プログラムはエラー メッセージを出力した後も実行を継続し、正常に終了します:
$ python err.py
エラー: ルート: 整数の除算またはゼロによるモジュロ
トレースバック (最後の呼び出し):
ファイル「err.py」、メイン
の 12 行目
bar('0')
ファイル「err.py」、8 行目、bar
foo(s) * 2
を返します
ファイル「err.py」、5 行目、foo
10 / int(s) を返します
ZeroDivisionError: 整数の除算またはゼロによるモジュロ
終了
構成を通じて、ロギングによってエラーをログ ファイルに記録し、その後のトラブルシューティングを容易にすることもできます。
# err.py
class FooError(StandardError):
パス
n = int(s)
n==0 の場合:
Raise FooError('無効な値: %s' % s)
10 / n を返します
実行すると、最終的に独自に定義したエラーを追跡できます:
$ python err.py
トレースバック (最後の呼び出し):
...
__main__.FooError: 無効な値: 0
必要な場合にのみ独自のエラー タイプを定義します。 Python の組み込みエラー タイプ (ValueError、TypeError など) を選択できる場合は、Python の組み込みエラー タイプを使用してみてください。
# err.py
def foo(s):
n = int(s)
10 / n を返します
試してみてください:
return foo(s) * 2
StandardError を除く、e:
print 'エラー!'
レイズ
bar('0')
bar() 関数では明らかにエラーをキャッチしていますが、Error! を出力した後、raise ステートメントを通じてエラーをスローしています。これは不健全ではないでしょうか。
試してみてください:
10/0
ZeroDivisionError を除く:
Raise ValueError('入力エラー!')
合理的な変換ロジックがある限り問題ありませんが、IOError を無関係な ValueError に変換してはなりません。