web-dev-qa-db-ja.com

Boto3、python、そしてエラーの処理方法

私が行ったスクリプト言語としてpythonを使ったばかりで、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ステータスコードをオンにすることができないからです(IAMのAWS APIドキュメントによれば409は既に存在します)。これは私が私が何か間違った方法でやっているに違いないと思うようにします。最適な方法は、boto3が例外をスローしないことですが、jutsは常にAPI呼び出しがどのように行われたかを反映したオブジェクトを返します。

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

どうもありがとう!

142
SQDK

例外に含まれている応答を使用してください。これが一例です。

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 boto3
from botocore.exceptions import ClientError, ParamValidationError

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 ParamValidationError as e:
    print("Parameter validation error: %s" % e)
except ClientError as e:
    print("Unexpected error: %s" % e)

残念ながら、これらの例外に関する文書は現在ありません。

312
jarmod

@jarmodで指摘されている「リソースに例外がない」問題を更新したものです(該当する場合は、遠慮なく回答を更新してください)

私は以下のコードをテストしました、そしてそれはうまく動きます。それはすることのために 'resources'を使いますが、client.exceptionsをキャッチします - それは 'いくぶん間違って見える'けれども...それは良いテストをします、例外クラスは例外時にデバッガを使用して調べたときに表示され一致する...

すべてのリソースやクライアントに適用できるわけではありませんが、データフォルダ(別名s3バケット)には有効です。

lab_session = boto3.Session() 
c = lab_session.client('s3') #this client is only for exception catching

try:
    b = s3.Bucket(bucket)
    b.delete()
except c.exceptions.NoSuchBucket as e:
    #ignoring no such bucket exceptions
    logger.debug("Failed deleting bucket. Continuing. {}".format(e))
except Exception as e:
    #logging all the others as warning
    logger.warning("Failed deleting bucket. Continuing. {}".format(e))

お役に立てれば...

10
R. Simac

あるいはクラス名の比較。

except ClientError as e:
    if 'EntityAlreadyExistsException' == e.__class__.__name__:
        # handle specific error

それらは動的に作成されるので、クラスをインポートして本物のPythonを使ってキャッチすることは決してできません。

1
jmoz

例外は、このパッケージの画面に表示されるすべての例外を一覧にしたものではないため、非常に便利です。これを実行するために使用したコードは次のとおりです。

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 __== '__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
0
jamescampbell

Python3を使用してsign_up API(AWS Cognito)を呼び出す場合、次のコードを使用できます。

def registerUser(userObj):
    ''' Registers the user to AWS Cognito.
    '''

    # Mobile number is not a mandatory field. 
    if(len(userObj['user_mob_no']) == 0):
        mobilenumber = ''
    else:
        mobilenumber = userObj['user_country_code']+userObj['user_mob_no']

    secretKey = bytes(settings.SOCIAL_AUTH_COGNITO_SECRET, 'latin-1')
    clientId = settings.SOCIAL_AUTH_COGNITO_KEY 

    digest = hmac.new(secretKey,
                msg=(userObj['user_name'] + clientId).encode('utf-8'),
                digestmod=hashlib.sha256
                ).digest()
    signature = base64.b64encode(digest).decode()

    client = boto3.client('cognito-idp', region_name='eu-west-1' ) 

    try:
        response = client.sign_up(
                    ClientId=clientId,
                    Username=userObj['user_name'],
                    Password=userObj['password1'],
                    SecretHash=signature,
                    UserAttributes=[
                        {
                            'Name': 'given_name',
                            'Value': userObj['given_name']
                        },
                        {
                            'Name': 'family_name',
                            'Value': userObj['family_name']
                        },
                        {
                            'Name': 'email',
                            'Value': userObj['user_email']
                        },
                        {
                            'Name': 'phone_number',
                            'Value': mobilenumber
                        }
                    ],
                    ValidationData=[
                        {
                            'Name': 'email',
                            'Value': userObj['user_email']
                        },
                    ]
                    ,
                    AnalyticsMetadata={
                        'AnalyticsEndpointId': 'string'
                    },
                    UserContextData={
                        'EncodedData': 'string'
                    }
                )
    except ClientError as error:
        return {"errorcode": error.response['Error']['Code'],
            "errormessage" : error.response['Error']['Message'] }
    except Exception as e:
        return {"errorcode": "Something went wrong. Try later or contact the admin" }
    return {"success": "User registered successfully. "}

error.response ['Error'] ['Code']はInvalidPasswordException、UsernameExistsExceptionなどになります。したがって、メイン関数または関数を呼び出す場所で、ユーザーに意味のあるメッセージを提供するロジックを作成できます。

応答の例(error.response):

{
  "Error": {
    "Message": "Password did not conform with policy: Password must have symbol characters",
    "Code": "InvalidPasswordException"
  },
  "ResponseMetadata": {
    "RequestId": "c8a591d5-8c51-4af9-8fad-b38b270c3ca2",
    "HTTPStatusCode": 400,
    "HTTPHeaders": {
      "date": "Wed, 17 Jul 2019 09:38:32 GMT",
      "content-type": "application/x-amz-json-1.1",
      "content-length": "124",
      "connection": "keep-alive",
      "x-amzn-requestid": "c8a591d5-8c51-4af9-8fad-b38b270c3ca2",
      "x-amzn-errortype": "InvalidPasswordException:",
      "x-amzn-errormessage": "Password did not conform with policy: Password must have symbol characters"
    },
    "RetryAttempts": 0
  }
}

さらに参照するには: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.sign_up

0
Haris Np