Python で例外を処理しない方法
多くの人が例外を間違った方法で処理しているのを目にします。これはあなたにも当てはまるのではないでしょうか。次の状況は見覚えがありますか?
コードを書いていますが、使用しているライブラリで例外が発生する可能性があることがわかっています。正確にはどれか覚えていません。この時点で、いわゆるキャッチオール ブロックを使用して楽しいことを続けたくなるでしょう。
目次
最悪の方法
最悪の場合は、何でもキャッチする try-except ブロックを作成することです。キャッチオールとは、次のような意味です:
try: ... except: pass
このようなキャッチオール ブロックは次の理由で不適切です:
<オール>
さらに、空の except は KeyboardInterrupt
を含むすべてをキャッチします (コントロール + c)、SystemExit
、さらには NameErrors
!これは、次のコードをきれいに停止できないことを意味します:
from time import sleep while True: try: print("Try and stop me") sleep(1) except: print("Don't.. stop.. me now!")
お気軽にお試しください。このプログラムを停止するには、ターミナル ウィンドウを閉じるか、Python プロセスを強制終了する必要があります。
すべての例外をキャッチするより良い方法
対照的に、except Exception
を使用すると、 、まだあまりにも多くの例外をキャッチする手っ取り早い汚い方法ですが、少なくとも実行中のプロセスを適切に停止することができます:
from time import sleep while True: try: print("Try and stop me") sleep(1) except Exception: print("Ok I'll stop!")
Exception
キャッチ時 SystemExit
をキャッチできません 、 KeyboardInterrupt
およびその他のそのような例外。なぜですか?
すべての例外は BaseException
というクラスから継承します .公式ドキュメントによると、「try
で except
を含むステートメント 特定のクラスに言及する句の場合、その句は、そのクラスから派生したすべての例外クラスも処理します。」空の except
except BaseException
と同等です 、したがって、考えられるすべての例外をキャッチします。
対照的に、クラス Exception
は次のように定義されています。すべてのユーザー定義の例外も、このクラスから派生する必要があります。」
さらに悪化
次の例では、os ライブラリを使用して現在の作業ディレクトリを取得します。しかし、太った小指がタイプミスを犯してしまいました:
import os try: working_dir = os.getcdw() print(working_dir) except: print('error')
os.getcdw
だから os モジュールの関数ではない場合、NameError がスローされます。失敗する代わりに、except 句はエラーをキャッチし、「エラー」を出力し、あからさまなタイプミスにもかかわらず、プログラムは続行します。残念ながら、これは Exception
をキャッチしても解決できません。
どうやら、ステップ 1 のちょっとしたトリックですべての問題が解決するわけではありません。 すべきこと
扱えるものをキャッチ
例外についてよく耳にするフレーズは、次のとおりです。処理できるものをキャッチ .多くの開発者は、例外を直接処理したくなりますが、例外を実際に処理できるプログラムの一部に例外を伝播させる方がよい場合がよくあります。
たとえば、ファイルを開いてロードするテキスト エディターの部分を考えてみましょう。それを OpenFile
と呼びましょう。 クラス。ユーザーが存在しないファイルを開くように要求した場合は、そのエラーを直接処理するか、伝播させることができます。
この場合、 OpenFile
であるため、例外を呼び出し元に伝播する方が適切です この例外が呼び出し元にとってどれほど悪いかわかりません。発信者は複数の方法で状況を処理できます:
- 代わりにその名前で新しいファイルを作成して続行することもできます
- 呼び出し元がファイルを必要とする場合があります。その場合、エラー ダイアログを表示して、このファイルが存在しないことをユーザーに通知できます。
いずれにせよ、OpenFile
には達していません FileNotFoundError
の場合にどうするかを決定するクラス .
では、例外は常に伝搬されるべきでしょうか?いいえ。FileOpen クラスで処理できる可能性のある例外は、TimeoutError
です。 .たとえば、呼び出し元にエラーを迷惑をかけずに、数回再試行することをお勧めします。これは OpenFile
の例外です 処理できるので、キャッチして再試行しても問題ありません。
結論
どのような状況でも、処理できる以上の例外をキャッチするべきではありません。ブロック以外のブランケットは、バグや予測不能なコードのレシピです。言い換えれば、あなたが扱えるものをキャッチしてください。
「処理できるものをキャッチする」マトラを念頭に置いてコードを記述する場合、キャッチオール ブロックを記述することはすべてのルールに違反しています。だからやめてください。演習として、既存のコードの一部を見直して、この新しい知識で改善できるかどうかを確認できます!
Python