example cli aws python amazon-web-services boto boto3

cli - Boto3, python y como manejar errores



install boto3 (6)

Debe hacer algo cuando no puede manejar el problema. En este momento está devolviendo la excepción real. Por ejemplo, si no es un problema que el usuario ya exista y desea usarlo como una función get_or_create, tal vez maneje el problema devolviendo el objeto de usuario existente.

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.

Dicho esto, tal vez sea un problema para su aplicación, en cuyo caso desea colocar el controlador de excepciones alrededor del código que llamó a su función de creación de usuario y dejar que la función de llamada determine cómo tratarla, por ejemplo, preguntando el usuario ingrese otro nombre de usuario, o lo que tenga sentido para su aplicación.

Acabo de elegir Python como mi lenguaje de scripting y estoy tratando de imaginar cómo hacer un manejo adecuado de errores con boto3.

Estoy tratando de crear un usuario de IAM:

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

Cuando la llamada a create_user tiene éxito, obtengo un objeto limpio que contiene el código de estado http de la llamada API y los datos del usuario recién creado.

Ejemplo:

{''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'' } }

Esto funciona muy bien. Pero cuando esto falla (como si el usuario ya existe), solo obtengo un objeto de tipo botocore.exceptions.ClientError con solo texto para decirme qué salió mal.

Ejemplo: ClientError (''Se produjo un error (EntityAlreadyExists) al llamar a la operación CreateUser: el usuario con el nombre omitido ya existe.'')

Esto (AFAIK) hace que el manejo de errores sea muy difícil porque no puedo simplemente activar el código de estado http resultante (409 para el usuario ya existe de acuerdo con los documentos de la API de AWS para IAM). Esto me hace pensar que debo estar haciendo algo de manera incorrecta. La forma óptima sería que boto3 nunca arroje excepciones, pero los juts siempre devuelven un objeto que refleje cómo fue la llamada API.

¿Alguien puede aclararme sobre este tema o señalarme en la dirección correcta?

¡Muchas gracias!


Lo encontré muy útil, ya que las Excepciones no están documentadas para enumerar todas las excepciones en la pantalla para este paquete. Aquí está el código que solía hacerlo:

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])

Lo que resulta en:

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


O una comparación en el nombre de la clase, por ejemplo

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

Debido a que se crean dinámicamente, nunca puedes importar la clase y capturarla usando Python real.


Si está llamando a la API sign_up (AWS Cognito) usando Python3, puede usar el siguiente código.

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''] [''Código''] será InvalidPasswordException, UsernameExistsException, etc. Por lo tanto, en la función principal o donde está llamando a la función, puede escribir la lógica para proporcionar un mensaje significativo al usuario.

Un ejemplo para la respuesta (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 } }

Para mayor referencia: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.sign_up


Solo una actualización del problema ''sin excepciones en los recursos'' como lo señala @jarmod (no dude en actualizar su respuesta si a continuación parece aplicable)

He probado el siguiente código y funciona bien. Utiliza ''recursos'' para hacer las cosas, pero atrapa al client.exceptions . client.exceptions , aunque ''se ve'' algo mal ... prueba bien, las clases de excepción se muestran y coinciden cuando se considera el uso del depurador en el momento de la excepción ...

Es posible que no sea aplicable a todos los recursos y clientes, pero funciona para carpetas de datos (también conocidos como cubos 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))

Espero que esto ayude...


Use la respuesta contenida dentro de la excepción. Aquí hay un ejemplo:

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)

La respuesta dict en la excepción contendrá lo siguiente:

  • [''Error''][''Code''] por ejemplo, ''EntityAlreadyExists'' o ''ValidationError''
  • [''ResponseMetadata''][''HTTPStatusCode''] por ejemplo 400
  • [''ResponseMetadata''][''RequestId''] por ejemplo, ''d2b06652-88d7-11e5-99d0-812348583a35''
  • [''Error''][''Message''] por ejemplo, "Se produjo un error (EntityAlreadyExists) ..."
  • [''Error''][''Type''] ej. ''Remitente''

Para obtener más información, consulte el botocore.readthedocs.io/en/latest/… .

[Actualizado: 2018-03-07]

AWS Python SDK ha comenzado a exponer excepciones de servicio en clients (aunque no en resources ) que puede capturar explícitamente, por lo que ahora es posible escribir ese código de la siguiente manera:

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)

Desafortunadamente, actualmente no hay documentación para estas excepciones.