[解決済み】なぜ "except: pass "は悪いプログラミング手法なのか?
質問
他のStack Overflowの質問で、よくコメントを見かけます。
except: pass
は推奨されません。なぜいけないのでしょうか?私は時々、エラーが何であるかは気にせず、ただコードを続行したいのです。
try:
something
except:
pass
なぜ
except: pass
ブロックが悪いのか?何が悪いのでしょうか?それは、私が
pass
をエラーにしたり
except
何かエラーがありますか?
解決方法は?
正しく推測されるように、それには2つの側面があります。キャッチする
任意の
の後に例外型を指定しないことで、エラー
except
で、何もせずにそのまま渡す。
私の説明は「ちょっと」長いので、Tl;drで説明すると、以下のようになります。
- をキャッチしないでください。 任意の エラー . 常に、どの例外から回復する用意があるかを指定し、それらの例外のみをキャッチするようにします。
- except ブロックはなるべく使わない . 明示的に望まれていない限り、これは通常、良い兆候ではありません。
でも、詳しく説明しましょう。
をキャッチしないでください。 任意の エラー
を使用する場合
try
ブロックは、通常、例外がスローされる可能性があることを知っているからこそ行うのです。そのため、あなたはまた、すでにおおよその
何
が壊れる可能性があり、どのような例外が投げられるか。そのような場合、例外をキャッチするのは
積極的に回復する
ということです。つまり、例外に備え、例外が発生した場合に従うべき代替案を持っているのです。
例えば、ユーザーに数値の入力を求める場合、入力された数値を変換するために
int()
を発生させるかもしれません。
ValueError
. これは、ユーザーにもう一度試してもらうことで簡単に回復できます。
ValueError
を実行し、再度ユーザーにプロンプトを表示するのが適切なプランでしょう。別の例として、あるファイルから設定を読み込もうとしたときに、そのファイルがたまたま存在しなかったとします。設定ファイルであるため、フォールバックとしてデフォルトの設定がある可能性があります。そのため
FileNotFoundError
で、単純にデフォルトの設定を適用するのが、ここでは良い計画でしょう。さて、この2つのケースでは、非常に具体的な例外が想定され、そこから回復するための計画も同様に具体的なものとなっています。そのため、それぞれのケースで、明示的に
except
その特定の
は例外となります。
しかし、仮に すべて その場合、リカバリーできる例外の他に、予想外の例外が発生する可能性があります。
先ほどの設定ファイルの例で考えてみましょう。ファイルが見つからない場合、デフォルトの設定を適用し、後で設定を自動的に保存することにするかもしれません(そうすれば、次回からはファイルが存在することになります)。ここで
IsADirectoryError
または
PermissionError
の代わりに このような場合、おそらくそのまま続行することはありません。デフォルトの設定を適用することはできますが、後でファイルを保存することができなくなります。また、ユーザーは独自の設定を望んでいる可能性が高いので、デフォルト値を使用することは望ましくないでしょう。そこで、そのことをすぐにユーザーに伝え、おそらくプログラムの実行も中断させたい。しかし、これは小さなコード部分の奥深くで行うことではありません。これはアプリケーションレベルの重要なことなので、トップで処理されるべきなのです。
また、別の簡単な例として
Python 2 のイディオム
のドキュメントを参照してください。ここでは、コードに単純なタイプミスが存在し、それが原因でコードが壊れています。なぜなら、私たちは
あらゆる
例外が発生すると
NameError
s
と
SyntaxError
s
. どちらもプログラミング中に誰にでも起こるミスで、コードを出荷するときには絶対に入れたくないミスです。しかし、それらもキャッチしてしまったために、そこで発生したことすらわからなくなり、正しくデバッグするための手助けを失ってしまうのです。
しかし、もっと危険な例外もあり、それに対する備えはほとんどない。例えば、以下のようなものです。 システムエラー これは、何かもっと複雑なことが起こっていて、現在のタスクが続けられなくなる可能性があることを意味します。
いずれにせよ、コードの小規模な部分ですべてに備えるということはまずありえないので、そこは本当に備えている例外だけをキャッチすればいいのです。人によっては、少なくとも
Exception
のようなものは含まれないので
SystemExit
と
KeyboardInterrupt
どの
意図的に
はアプリケーションを終了させるものですが、これではまだあまりに不特定多数であるというのが私の意見です。私が個人的にキャッチボールを容認しているのは、1箇所だけです。
Exception
または単に
任意の
この例外ハンドラは、準備されていない例外をログに記録することを唯一の目的としています。そうすることで、予期せぬ例外に関する情報をできるだけ多く保持することができます。この情報を使って、明示的に例外を処理するようにコードを拡張したり(回復できる場合)、バグの場合には、二度と発生しないことを確認するためのテストケースを作成したりできます。しかし、もちろん、それは想定していた例外だけを捕捉していた場合にのみ有効で、想定外の例外は自然に湧き上がってくるのです。
except ブロックはなるべく使わない
特定の例外の一部を明示的に捕捉する場合、何もしない方が良い場合が多々あります。そのような場合、単に
except SomeSpecificException: pass
がちょうどいい。しかし、ほとんどの場合、(前述のように)回復処理に関連するコードが必要になる可能性があるため、そうではありません。例えば、アクションを再試行したり、代わりにデフォルト値を設定するようなものです。
しかし、そうでない場合、例えば、成功するまで繰り返すようなコードになっている場合は、パスだけで十分です。先ほどの例で言えば、ユーザーに数字を入力してもらうとします。ユーザーは私たちが求めたことを実行しないのが好きだということを知っているので、最初の段階でループに入れるだけにして、次のようにします。
def askForNumber ():
while True:
try:
return int(input('Please enter a number: '))
except ValueError:
pass
例外が発生しなくなるまで試行錯誤を続けるので、exceptブロックの中で特別なことをする必要はありませんから、これでよいのです。しかし、もちろん、なぜ入力を繰り返さなければならないのか、少なくともユーザーに何らかのエラーメッセージを示したいという意見もあるでしょう。
しかし、他の多くの場合、単に
except
は、キャッチする例外の準備が整っていないことを示すものです。例外が単純なものでない限り (
ValueError
または
TypeError
)、パスできる理由は明白なので、パスだけを避けるようにしましょう。もし本当に何もすることがないのであれば(そしてあなたがそれについて絶対に確信しているなら)、なぜそうなのかというコメントを追加することを検討してください。そうでなければ、exceptブロックを拡張して実際にいくつかの回復コードを含むようにしてください。
except: pass
しかし、最も悪いのは、その両方を組み合わせたものです。これはつまり、私たちが進んでキャッチしている 任意の エラーに対しての準備が全くできていないにもかかわらず そして また、それに対して何もしない。あなたは 少なくとも エラーを記録し、アプリケーションを終了させるために再レイズする可能性もあります (MemoryError の後に通常通り続けられる可能性は低いです)。しかし、ただ渡すだけでは、アプリケーションをある程度維持するだけでなく(もちろんどこでキャッチするかによりますが)、すべての情報を捨ててしまい、エラーを発見することが不可能になります。
つまり、結論は それ以外の例外は、修正すべきミスか、いずれにせよ準備不足である可能性が高い。パッシング 特定 の例外は、本当に何もする必要がないのであれば、問題ありません。それ以外の場合は、ただの思い込みと怠慢の表れです。そして、それは絶対に直した方がいい。
関連
-
Python 入出力と高次代入の基礎知識
-
[解決済み】SyntaxError: デフォルト以外の引数がデフォルトの引数に続く
-
[解決済み] UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)
-
[解決済み] 複数の例外を1行でキャッチする(ブロックを除く)
-
[解決済み] 変数を参照渡しする方法を教えてください。
-
[解決済み] PHPで有用なエラーメッセージを得るにはどうしたらよいですか?
-
[解決済み] なぜすべてのブロックを "try"-"catch "で包んではいけないのですか?
-
[解決済み】PandasでSettingWithCopyWarningに対処する方法
-
[解決済み】C#で例外をキャッチして再スローする理由とは?
-
[解決済み】Pythonでtry-except-elseを使用するのは良い習慣ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python カメの描画コマンドとその例
-
Python百行で韓服サークルの画像クロールを実現する
-
Python Pillow Image.save jpg画像圧縮問題
-
Python 入出力と高次代入の基礎知識
-
[解決済み】csv.Error:イテレータはバイトではなく文字列を返すべき
-
[解決済み】TypeError: 系列を <class 'float'> に変換することができません。
-
[解決済み】"No JSON object could be decoded "よりも良いエラーメッセージを表示する。
-
[解決済み】Python: SyntaxError: キーワードは式になり得ない
-
[解決済み] すべての例外をキャッチする `try`/`except` ブロックはどのように書けばよいですか?
-
[解決済み] 例外を正しく無視する方法