267

boto3 で適切なエラー処理を行う方法を理解しようとしています。

IAM ユーザーを作成しようとしています:

def create_user(username, iam_conn):
    try:
        user = iam_conn.create_user(UserName=username)
        return user
    except Exception as e:
        return e

create_user の呼び出しが成功すると、API 呼び出しの http ステータス コードと新しく作成されたユーザーのデータを含むきちんとしたオブジェクトを取得します。

例:

{'ResponseMetadata': 
      {'HTTPStatusCode': 200, 
       'RequestId': 'omitted'
      },
 u'User': {u'Arn': 'arn:aws:iam::omitted:user/omitted',
           u'CreateDate': datetime.datetime(2015, 10, 11, 17, 13, 5, 882000, tzinfo=tzutc()),
           u'Path': '/',
           u'UserId': 'omitted',
           u'UserName': 'omitted'
          }
}

これはうまくいきます。しかし、これが失敗した場合 (ユーザーが既に存在する場合など) は、タイプ botocore.exceptions.ClientError のオブジェクトを取得し、テキストだけで何が問題なのかを教えてくれます。

例: ClientError('CreateUser 操作の呼び出し時にエラーが発生しました (EntityAlreadyExists): 名前が省略されたユーザーは既に存在します。',)

結果のhttpステータスコードをオンにすることはできないため、これ(AFAIK)はエラー処理を非常に困難にします(IAMのAWS APIドキュメントによると、ユーザーの409はすでに存在します)。これは、私が間違った方法で何かをしているに違いないと私に思わせます。最適な方法は、boto3 が例外をスローしないことですが、juts は常に API 呼び出しがどのように行われたかを反映するオブジェクトを返します。

誰かがこの問題について私を啓発したり、正しい方向に向けたりできますか?

4

10 に答える 10

521

例外に含まれる応答を使用します。次に例を示します。

import boto3
from botocore.exceptions import ClientError

try:
    iam = boto3.client('iam')
    user = iam.create_user(UserName='fred')
    print("Created user: %s" % user)
except ClientError as e:
    if e.response['Error']['Code'] == 'EntityAlreadyExists':
        print("User already exists")
    else:
        print("Unexpected error: %s" % e)

例外の応答辞書には、次のものが含まれます。

  • ['Error']['Code']例: 「EntityAlreadyExists」または「ValidationError」
  • ['ResponseMetadata']['HTTPStatusCode']例: 400
  • ['ResponseMetadata']['RequestId']例: 'd2b06652-88d7-11e5-99d0-812348583a35'
  • ['Error']['Message']例: 「エラーが発生しました (EntityAlreadyExists) ...」
  • ['Error']['Type']例: 「送信者」

詳細については、次を参照してください。

[更新: 2018-03-07]

AWS Python SDK は、明示的にキャッチできるクライアント(リソースではなく) でサービス例外を公開し始めたため、次のようにそのコードを記述できるようになりました。

import botocore
import boto3

try:
    iam = boto3.client('iam')
    user = iam.create_user(UserName='fred')
    print("Created user: %s" % user)
except iam.exceptions.EntityAlreadyExistsException:
    print("User already exists")
except botocore.exceptions.ParamValidationError as e:
    print("Parameter validation error: %s" % e)
except botocore.exceptions.ClientError as e:
    print("Unexpected error: %s" % e)

残念ながら、現在、これらのエラー/例外に関するドキュメントはありませんが、次のようにコア エラーのリストを取得できます。

import botocore
import boto3
[e for e in dir(botocore.exceptions) if e.endswith('Error')]

botocore と boto3 の両方をインポートする必要があることに注意してください。botocore のみをインポートすると、botocore には という名前の属性がないことがわかりますexceptions。これは、例外が boto3 によって botocore に動的に読み込まれるためです。

次のように、サービス固有の例外のリストを取得できます (iam必要に応じて、関連するサービスに置き換えてください)。

import boto3
iam = boto3.client('iam')
[e for e in dir(iam.exceptions) if e.endswith('Exception')]

[更新: 2021-09-07]

前述のクライアント例外メソッドに加えて、aws-error-utilsという名前のサードパーティ ヘルパー パッケージもあります。

于 2015-11-12T02:39:14.480 に答える
33

例外は文書化されていないため、このパッケージの画面にすべての例外をリストすることは非常に便利であることがわかりました。これが私がそれを行うために使用したコードです:

import botocore.exceptions
def listexns(mod):
    #module = __import__(mod)
    exns = []
    for name in botocore.exceptions.__dict__:
        if (isinstance(botocore.exceptions.__dict__[name], Exception) or
            name.endswith('Error')):
            exns.append(name)
    for name in exns:
        print('%s.%s is an exception type' % (str(mod), name))
    return

if __name__ == '__main__':
    import sys
    if len(sys.argv) <= 1:
        print('Give me a module name on the $PYTHONPATH!')
    print('Looking for exception types in module: %s' % sys.argv[1])
    listexns(sys.argv[1])

結果は次のとおりです。

Looking for exception types in module: boto3
boto3.BotoCoreError is an exception type
boto3.DataNotFoundError is an exception type
boto3.UnknownServiceError is an exception type
boto3.ApiVersionNotFoundError is an exception type
boto3.HTTPClientError is an exception type
boto3.ConnectionError is an exception type
boto3.EndpointConnectionError is an exception type
boto3.SSLError is an exception type
boto3.ConnectionClosedError is an exception type
boto3.ReadTimeoutError is an exception type
boto3.ConnectTimeoutError is an exception type
boto3.ProxyConnectionError is an exception type
boto3.NoCredentialsError is an exception type
boto3.PartialCredentialsError is an exception type
boto3.CredentialRetrievalError is an exception type
boto3.UnknownSignatureVersionError is an exception type
boto3.ServiceNotInRegionError is an exception type
boto3.BaseEndpointResolverError is an exception type
boto3.NoRegionError is an exception type
boto3.UnknownEndpointError is an exception type
boto3.ConfigParseError is an exception type
boto3.MissingParametersError is an exception type
boto3.ValidationError is an exception type
boto3.ParamValidationError is an exception type
boto3.UnknownKeyError is an exception type
boto3.RangeError is an exception type
boto3.UnknownParameterError is an exception type
boto3.AliasConflictParameterError is an exception type
boto3.PaginationError is an exception type
boto3.OperationNotPageableError is an exception type
boto3.ChecksumError is an exception type
boto3.UnseekableStreamError is an exception type
boto3.WaiterError is an exception type
boto3.IncompleteReadError is an exception type
boto3.InvalidExpressionError is an exception type
boto3.UnknownCredentialError is an exception type
boto3.WaiterConfigError is an exception type
boto3.UnknownClientMethodError is an exception type
boto3.UnsupportedSignatureVersionError is an exception type
boto3.ClientError is an exception type
boto3.EventStreamError is an exception type
boto3.InvalidDNSNameError is an exception type
boto3.InvalidS3AddressingStyleError is an exception type
boto3.InvalidRetryConfigurationError is an exception type
boto3.InvalidMaxRetryAttemptsError is an exception type
boto3.StubResponseError is an exception type
boto3.StubAssertionError is an exception type
boto3.UnStubbedResponseError is an exception type
boto3.InvalidConfigError is an exception type
boto3.InfiniteLoopConfigError is an exception type
boto3.RefreshWithMFAUnsupportedError is an exception type
boto3.MD5UnavailableError is an exception type
boto3.MetadataRetrievalError is an exception type
boto3.UndefinedModelAttributeError is an exception type
boto3.MissingServiceIdError is an exception type
于 2019-06-20T16:58:50.880 に答える
-5

問題の処理に失敗した場合は、何かを行う必要があります。現在、実際の例外を返しています。たとえば、ユーザーが既に存在することが問題ではなく、それを get_or_create 関数として使用したい場合は、既存のユーザー オブジェクトを返すことで問題を処理できます。

try:
    user = iam_conn.create_user(UserName=username)
    return user
except botocore.exceptions.ClientError as e:

    #this exception could actually be other things other than exists, so you want to evaluate it further in your real code.
    if e.message.startswith(
        'enough of the exception message to identify it as the one you want')

        print('that user already exists.')
        user = iam_conn.get_user(UserName=username)
        return user

    elif e.message.some_other_condition:

         #something else
    else:
         #unhandled ClientError
         raise(e)
except SomeOtherExceptionTypeYouCareAbout as e:
    #handle it

# any unhandled exception will raise here at this point.
# if you want a general handler

except Exception as e:
    #handle it.

とはいえ、アプリの問題かもしれません。その場合、ユーザーの作成関数を呼び出したコードの周りに例外ハンドラーを配置し、呼び出し元の関数に処理方法を決定させます。たとえば、次のように尋ねます。ユーザーが別のユーザー名を入力するか、アプリケーションにとって意味のあるものなら何でも。

于 2015-10-11T17:46:09.780 に答える