私はあなたが考えているのと同様の方法でこれを行います.「合格してはならない」ガンダルフ例外ハンドラーを使用して、except Exception
システムを終了しないすべての例外をキャッチしset
、合格して再終了する必要がある例外のブラックリストを作成します-上げた。
Gandalf ハンドラーを使用すると、コール スタックの上位に他のハンドラーが存在しない場合、(すべてのシステム終了例外)および(すべてのシステム終了例外) が確実GeneratorExit
に渡され、プログラムが終了します。ここで、キャッチされた例外が実際にブラックリストの例外のセットに属していることを確認して、再度確認できます。SystemExit
KeyboardInterrupt
type(e)
__class__
e
raise
小さなデモンストレーションとして:
import exceptions # Py2.x only
# dictionary holding {exception_name: exception_class}
excptDict = vars(exceptions)
exceptionNames = ['MemoryError', 'OSError', 'SystemError'] # and others
# set containing black-listed exceptions
blackSet = {excptDict[exception] for exception in exceptionNames}
blackSet = {OSError, SystemError, MemoryError}
これで、処理したくないシステム外の例外のクラスが保持されます。
ブロックは次のtry-except
ようになります。
try:
# calls that raise exceptions:
except Exception as e:
if type(e) in blackSet: raise e # re-raise
# else just handle it
を使用してすべての例外をキャッチする例BaseException
は、私の言いたいことを説明するのに役立ちます。(これはデモンストレーションのみを目的として行われ、このレイズが最終的にどのようにプログラムを終了させるかを確認するためです)。注意してください:私はあなたが使用することをお勧めしていませんBaseException
; どの例外が実際に「パススルー」して終了を引き起こすか (つまり、BaseException
キャッチするすべて)を示すために使用しています。
for i, j in excptDict.iteritems():
if i.startswith('__'): continue # __doc__ and other dunders
try:
try:
raise j
except Exception as ex:
# print "Handler 'Exception' caught " + str(i)
if type(ex) in blackSet:
raise ex
except BaseException:
print "Handler 'BaseException' caught " + str(i)
# prints exceptions that would cause the system to exit
Handler 'BaseException' caught GeneratorExit
Handler 'BaseException' caught OSError
Handler 'BaseException' caught SystemExit
Handler 'BaseException' caught SystemError
Handler 'BaseException' caught KeyboardInterrupt
Handler 'BaseException' caught MemoryError
Handler 'BaseException' caught BaseException
最後に、この Python 2/3 に依存しないようにするために、try
それが失敗した場合 (Python 3 ではそうです)、すべての;を含むimport exceptions
インポートにフォールバックできます。名前で辞書を検索するので、違いはありません。builtins
Exceptions
try:
import exceptions
excDict = vars(exceptions)
except ImportError:
import builtins
excDict = vars(builtins)
これを実際に行うためのよりスマートな方法があるかどうかはわかりません。 別の解決策はtry-except
、 signleを使用する代わりにexcept
、ブラックリストに記載された例外用と一般的なケース用の 2 つのハンドラーを持つことです。
try:
# calls that raise exceptions:
except tuple(blackSet) as be: # Must go first, of course.
raise be
except Exception as e:
# handle the rest