web-dev-qa-db-ja.com

例外を適切に無視する方法

例外を処理せずにtry-exceptを実行したいだけの場合は、Pythonでどのようにしますか。

次のようにするのが正しい方法ですか?

try:
    shutil.rmtree(path)
except:
    pass
671
Joan Venge
try:
  doSomething()
except: 
  pass

または

try:
  doSomething()
except Exception: 
  pass

違いは、最初のものはKeyboardInterruptSystemExit、およびそのようなものをキャッチすることです。これらはexceptions.BaseExceptionからではなく、直接exceptions.Exceptionから派生しています。
詳細はドキュメントを参照してください。

923
vartec

一般的には、あなたが興味を持っているエラーのみを捉えることがベストプラクティスと考えられています。shutil.rmtreeの場合、おそらくOSErrorです。

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

黙ってそのエラーを無視したい場合は、次のようにします。

try:
    shutil.rmtree(path)
except OSError:
    pass

どうして?誤って(どういうわけか)関数に文字列ではなく整数を渡したとしましょう。

shutil.rmtree(2)

"TypeError:Unicodeへの強制:文字列またはバッファが必要、intが見つかりました" - おそらく無視したくないでしょうが、これはデバッグが困難な場合があります。

間違いなく を使用してすべてのエラーを無視したい場合は、そのままのexcept:ステートメントではなくExceptionをキャッチしてください。繰り返しますが、なぜでしょうか。

例外を指定しないと、 every exceptionがキャッチされます。例えば、sys.exit()で使用されるSystemExit例外が含まれます。

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

これを次のものと比較してください。これは正しく終了します。

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
Shell:~$ 

もっと良く振る舞うコードを書きたいのであれば、 OSError 例外はさまざまなエラーを表すことができますが、上の例ではErrno 2を無視したいだけなので、さらに具体的にします。

try:
    shutil.rmtree(path)
except OSError, e:
    if e.errno == 2:
        # suppress "No such file or directory" error
        pass
    else:
        # reraise the exception, as it's an unexpected error
        raise

import errnoifif e.errno == errno.ENOENT:に変更することもできます。

125
dbr

例外を処理せずにtry catchを実行したいだけの場合は、Pythonでどのようにしますか。

それはあなたが「取扱い」によって何を意味するかによります。

何もしないでそれをキャッチしようとしている場合は、投稿したコードが機能します。

例外がスタックに上がるのを止めずに例外に対してアクションを取りたいという場合は、次のようなものが必要です。

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown
109
Jason Baker

最初に私はジャックオコナーの答えを このスレッド から引用します。参照されたスレッドは閉じられたので、ここに書きます。

「Python 3.4では、これを行うための新しい方法があります。

from contextlib import suppress

with suppress(Exception):
    # your code

これを追加したコミットは次のとおりです。 http://hg.python.org/cpython/rev/406b47c64480

そして、これと作者Raymond Hettingerが、これと他のあらゆる種類のPythonの辛さについて話しています: https://youtu.be/OSGv2VnC0go?t=43m23s

これに私が追加したのは、Python 2.7に相当するものです。

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

それから、Python 3.4のようにそれを使います。

with ignored(Exception):
    # your code
76
Jabba

完全を期すために:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"

... pythonチュートリアル から。

また、このような例外を捕捉できることにも注意してください。

>>> try:
...     this_fails()
... except ZeroDivisionError as detail:
...     print 'Handling run-time error:', detail
54
cbare

例外を正しく無視する方法

これを行うにはいくつかの方法があります。

しかし、例の選択は一般的なケースをカバーしない単純な解決策を持っています。

例に固有のもの:

の代わりに

try:
    shutil.rmtree(path)
except:
    pass

これを行う:

shutil.rmtree(path, ignore_errors=True)

これはshutil.rmtreeに固有の引数です。次のようにしてヘルプを見ることができます。また、エラーに関する機能性も考慮に入れることができます。

>>> import shutil
>>> help(shutil.rmtree)

これは例の狭いケースだけをカバーしているので、これらのキーワード引数が存在しない場合にこれをどのように処理するかをさらに説明します。

一般的方法

上記では例の狭いケースしか扱っていないので、これらのキーワード引数が存在しない場合の対処方法をさらに説明します。

Python 3.4の新機能:

suppressコンテキストマネージャをインポートすることができます。

from contextlib import suppress

しかし、最も具体的な例外だけを抑制してください。

with suppress(FileNotFoundError):
    shutil.rmtree(path)

FileNotFoundErrorを黙って無視します。

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

docs から:

例外を完全に抑制する他のメカニズムと同様に、このコンテキストマネージャはプログラムの実行を黙って続けることが正しいことであると知られている非常に特定のエラーをカバーするためだけに使用されるべきです。

suppressFileNotFoundErrorはPython 3でのみ利用可能です。

コードをPython 2でも機能させたい場合は、次のセクションを参照してください。

Python 2と3:

例外を処理せずにtry/exceptを実行したいだけの場合は、Pythonでどのようにしますか。

次のようにするのが正しい方法ですか?

try :
    shutil.rmtree ( path )
except :
    pass

Python 2互換のコードでは、passが何もしないステートメントを持つ正しい方法です。しかし裸のexcept:をするとき、それはGeneratorExitKeyboardInterrupt、およびSystemExitを含むexcept BaseException:をすることと同じです、そして、一般的に、あなたはそれらの事を捕らえたくありません。

実際、あなたは可能な限り例外を命名する際に特定のものであるべきです。

これはPython(2) exception hierarchy の一部です、そしてあなたが見ることができるように、あなたがより一般的なExceptionsを捕らえれば、あなたは予期しなかった問題を隠すことができます:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

あなたはおそらくここでOSErrorをキャッチしたいでしょう、そしておそらくあなたが気にしない例外はディレクトリがない場合です。

errnoライブラリから that 特定のエラー番号を取得することができ、それがない場合は再利用できます。

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

注意してほしいのは、ベアレイズが元の例外を発生させることです。これはおそらくあなたが望んでいることです。例外処理でコードを明示的にpassに明示的に指定する必要はないので、より簡潔に記述します。

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 
40
Aaron Hall

例外を処理せずにtry catchを実行したいだけの場合は、Pythonでどのようにしますか。

これは、例外が何であるかを表示するのに役立ちます。

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

参考までにelse節はすべての例外の後に置くことができ、tryのコードが例外を引き起こさない場合にのみ実行されます。

9

Pythonでは、他の言語と同様に例外を処理しますが、違いは構文の違いです。例えば、

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

私は複数のコマンドのエラーを無視する必要があり、 fuckit トリックをしました

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()
1
citynorman