やろうとしたこと
AWS-SDKでは沢山の例外が存在するが、実際はいくつかの例外クラス以外はbotocore.errorfactory.****
のように実は逐次生成している。
(もちろんいくつかあるそのエラーに該当するならその例外クラスをtry~catch
で捕まえてあげればいい。)
今回はそのエラーのちゃんとコントロールしたのでその備忘録として記録する。
実際のコード例
import sys import traceback import boto3 cwl = boto3.client('cloudwatch') def set_default_metric_alarm(self, metric_name): try: response = cwl.put_metric_alarm( ) print(response) except ClientError: t, v, tb = sys.exc_info() trb = traceback.format_exception(t, v, tb)[-1] if re.search(r"NotFoundException", trb): raise #自作例外クラス except Exception: traceback.print_exc()
コードの解説
try-except節の使い方は特段変わったものではない。
まずboto3のエラーは基本的にClientErrorのサブクラスでraiseされているので、except節ではClientError
を設置する。
内部については少し説明しづらいのだが、Errorに関する情報が記載されている要素を抜き出し、正規表現でハンドリングしたいエラーが含まれるか探している。
もしかしたら他にいい方法があるかもしれないが、今の所これでうまく行っているように感じる。
ちょっと特殊?な例外ハンドリングのコード
またboto3特有のものではないが、余談として呼び出し元、呼び出し先においてtry-catch
節が設置されている場合のハンドリングについてもやってみたので、いい方法かわからないが記載しておく。
sns = boto3.client('sns') def test_boto3_request(value): try: try: sns.sns.get_platform_application_attributes( PlatformApplicationArn=value ) except ClientError: t, v, tb = sys.exc_info() trb = traceback.format_exception(t, v, tb)[-1] if re.search(r"NotFoundException", trb): raise PlatformApplicationNotFoundException else: traceback.print_exc() raise Exception except PlatformApplicationNotFoundException: print('handlig ok') except Exception as e: print("Unexpect Error Occurred") raise Exception if __name__ == "__main__": try: test_boto3_request(value) except Exception: traceback.print_exe()
コードの解説2
これも動作は単純だが次の問題を解決している。
とある理由により呼び出し元で基底Exception等のクラスを設置していた場合、呼び出し先で発生した例外を呼び出し元がキャッチしてしまいうまく例外コントロールできなかった。
これはtryをネストさせることで、あたかも元から自作の例外が発生しているように見せかけている。
一見無駄なネストに見えるのだが、一度ClientError
でひっかけて、自作例外をraiseするとうまく行かない。(多分自分が例外の伝搬について誤解している部分がある)
もうちょっといい方法がないか模索したい。
補足
コードについてはおそらく動作しない。実装の雰囲気だけ掴んでいただきたい。