Pythonパニック/エラー処理の延期

Goのエラー処理は、ossified例外メカニズムではなく、遅延ハンドラの新しい興味深いメカニズムに基づいて構築されています。 興味深い研究として、このようなエラー処理をPythonで実装しました。 誰も気にしないで





Goでのエラー処理の原則は次のとおりです。deferキーワードを指定し、その後、メソッドの終了時に実行される関数を呼び出します:通常またはパニック(エラーが発生した場合)。 例:



func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } defer src.Close() dst, err := os.Create(dstName) if err != nil { return } defer dst.Close() return io.Copy(dst, src) }
      
      







詳細はこちらをご覧ください 。 遅延関数を指定すると、引数は固定され、それらを含む関数の最後に呼び出しが発生します。 エラー状態で関数の実行を中断する場合は、 panic()関数を呼び出す必要があります。 この場合、逆の順序で、遅延関数が呼び出されます。 それらのいずれかでrecover()関数が呼び出された場合、エラー状態は削除され、メソッドから戻った後、プログラムは通常の順序で実行されます。



この動作は、言語の柔軟性により、Pythonで実装できます。 これを行うには、スタック上の特殊変数を使用して関数のハンドラーをハングアップし、リカバリーの場合に特別なステータスを設定する、対応する関数を宣言します。 このメカニズムのサポート機能を指定するために、保留中の機能を保存するためのリストを作成し、それらを呼び出すための例外をキャッチするデコレーターが使用されます。 コード:



 # Go-style error handling import inspect import sys def panic(x): raise Exception(x) def defer(x): for f in inspect.stack(): if '__defers__' in f[0].f_locals: f[0].f_locals['__defers__'].append(x) break def recover(): val = None for f in inspect.stack(): loc = f[0].f_locals if f[3] == '__exit__' and '__suppress__' in loc: val = loc['exc_value'] loc['__suppress__'].append(True) break return val class DefersContainer(object): def __init__(self): # List for sustain refer in shallow clone self.defers = [] def append(self, defer): self.defers.append(defer) def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): __suppress__ = [] for d in reversed(self.defers): try: d() except: __suppress__ = [] exc_type, exc_value, traceback = sys.exc_info() return __suppress__ def defers_collector(func): def __wrap__(*args, **kwargs): __defers__ = DefersContainer() with __defers__: func(*args, **kwargs) return __wrap__ @defers_collector def func(): f = open('file.txt', 'w') defer(lambda: f.close()) defer(lambda : print("Defer called!")) def my_defer(): recover() defer(lambda: my_defer()) print("Ok )") panic("WTF?") print("Never printed (((") func() print("Recovered!")
      
      







遅延呼び出しの引数を保持するためにlambdaを使用して、 deferステートメントの動作を繰り返します。



ニュアンスで機能的アイデンティティをテストしませんでした。 しかし、あなたが洗練する必要があるものを知っているなら、書いてください。



All Articles