J'essaie de comprendre comment gérer correctement les erreurs avec boto3.
J'essaie de créer un utilisateur IAM:
def create_user(username, iam_conn):
try:
user = iam_conn.create_user(UserName=username)
return user
except Exception as e:
return e
Lorsque l'appel à create_user réussit, j'obtiens un objet soigné qui contient le code d'état http de l'appel API et les données de l'utilisateur nouvellement créé.
Exemple:
{'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'
}
}
Cela fonctionne très bien. Mais lorsque cela échoue (comme si l'utilisateur existe déjà), je reçois simplement un objet de type botocore.exceptions.ClientError avec uniquement du texte pour me dire ce qui ne va pas.
Exemple: ClientError ('Une erreur s'est produite (EntityAlreadyExists) lors de l'appel de l'opération CreateUser: l'utilisateur avec un nom omis existe déjà.',)
Cela (AFAIK) rend la gestion des erreurs très difficile car je ne peux pas simplement activer le code d'état http résultant (409 pour l'utilisateur existe déjà selon les documents de l'API AWS pour IAM). Cela me fait penser que je dois faire quelque chose dans le mauvais sens. La manière optimale serait que boto3 ne lève jamais d'exceptions, mais les juts retournent toujours un objet qui reflète le déroulement de l'appel d'API.
Quelqu'un peut-il m'éclairer sur cette question ou me diriger dans la bonne direction?
Réponses:
Utilisez la réponse contenue dans l'exception. Voici un exemple:
Le dict de réponse dans l'exception contiendra les éléments suivants:
['Error']['Code']
par exemple 'EntityAlreadyExists' ou 'ValidationError'['ResponseMetadata']['HTTPStatusCode']
par exemple 400['ResponseMetadata']['RequestId']
par exemple «d2b06652-88d7-11e5-99d0-812348583a35»['Error']['Message']
par exemple "Une erreur s'est produite (EntityAlreadyExists) ..."['Error']['Type']
par exemple "Expéditeur"Pour plus d'informations, voir Gestion des erreurs botocore .
[Mise à jour: 2018-03-07]
Le kit SDK AWS Python a commencé à exposer des exceptions de service sur les clients (mais pas sur les ressources ) que vous pouvez explicitement intercepter, il est donc maintenant possible d'écrire ce code quelque chose comme ceci:
Malheureusement, il n'existe actuellement aucune documentation pour ces exceptions.
la source
200
dans votre chèque, car le code de retour peut être un2xx
code d'état HTTP différent (par exemple,204
lors de la suppression d'un coffre-fort ou d'une archive,201
lors de la création, etc.). Au mieux, on devrait vérifier un code non-4xx (par exemple,statusCode < 400
) mais c'est vraiment fragile et je ne le recommanderais pas de toute façon: il vaut mieux se fier àboto
lever des exceptions sur votre code.Je l'ai trouvé très utile, car les exceptions ne sont pas documentées, pour répertorier toutes les exceptions à l'écran pour ce package. Voici le code que j'ai utilisé pour le faire:
Ce qui se traduit par:
la source
Juste une mise à jour du problème `` aucune exception sur les ressources '' comme indiqué par @jarmod (n'hésitez pas à mettre à jour votre réponse si ci-dessous semble applicable)
J'ai testé le code ci-dessous et il fonctionne très bien. Il utilise des `` ressources '' pour faire des choses, mais attrape le
client.exceptions
- bien qu'il `` semble '' quelque peu faux ... il teste bien, les classes d'exception s'affichent et correspondent quand on regarde l'utilisation du débogueur au moment de l'exception ...Il peut ne pas être applicable à toutes les ressources et tous les clients, mais fonctionne pour les dossiers de données (aussi appelés compartiments s3).
J'espère que cela t'aides...
la source
s3.meta.client.exceptions.NoSuchBucket
s3
est la ressource de service, par exemples3 = boto3.resource('s3')
. Fonctionne également pour les ressources réelles, telles que les seaux:boto3.resource('s3').Bucket('bucket-name').meta.client.exceptions. ...
Comme quelques autres déjà mentionnés, vous pouvez intercepter certaines erreurs en utilisant le service client (
service_client.exceptions.<ExceptionClass>
) ou la ressource (service_resource.meta.client.exceptions.<ExceptionClass>
), mais elles ne sont pas bien documentées (aussi quelles exceptions appartiennent à quels clients). Voici donc comment obtenir la cartographie complète au moment de la rédaction (janvier 2020) dans la région UE (Irlande) (eu-west-1
):Voici un sous-ensemble du document assez volumineux:
la source
Ou une comparaison sur le nom de la classe, par exemple
Parce qu'ils sont créés dynamiquement, vous ne pouvez jamais importer la classe et l'attraper en utilisant du vrai Python.
la source
except Exception as e
et puis aurais des instructions if pour déterminer l'exception spécifique? En quoi est-ce différent / meilleur que la capture d'exceptions spécifiques? Ce sont plus de lignes, et vous devrez quand même importer la bibliothèque pour obtenir le nom de la classe. À moins que vous ne vouliez aller coder en dur le nom de l'exception. Dans l'ensemble, cela semble être une mauvaise façon de procéder.Si vous appelez l'API sign_up (AWS Cognito) à l'aide de Python3, vous pouvez utiliser le code suivant.
error.response ['Error'] ['Code'] sera InvalidPasswordException, UsernameExistsException etc. Donc, dans la fonction principale ou là où vous appelez la fonction, vous pouvez écrire la logique pour fournir un message significatif à l'utilisateur.
Un exemple pour la réponse (error.response):
Pour plus d'informations: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.sign_up
la source
Dans le cas où vous devez faire face au
logs
client sans doute hostile ( CloudWatch Logsput-log-events
), voici ce que j'ai dû faire pour intercepter correctement les exceptions du client Boto3:Cela fonctionne à la fois à la première tentative (avec LogStream vide) et aux suivantes.
la source
Suite à la mise à jour de @ armod sur les exceptions ajoutées directement sur les
client
objets. Je vais montrer comment vous pouvez voir toutes les exceptions définies pour votre classe client.Des exceptions sont générées dynamiquement lorsque vous créez votre client avec
session.create_client()
ouboto3.client()
. En interne, il appelle méthodebotocore.errorfactory.ClientExceptionsFactory._create_client_exceptions()
et remplit leclient.exceptions
champ avec des classes d'exceptions construites.Tous les noms de classe sont disponibles dans le
client.exceptions._code_to_exception
dictionnaire, vous pouvez donc répertorier tous les types avec l'extrait de code suivant:J'espère que ça aide.
la source
Vous devez faire quelque chose lorsqu'il ne parvient pas à gérer le problème. À l'heure actuelle, vous renvoyez l'exception réelle. Par exemple, si ce n'est pas un problème, l'utilisateur existe déjà et que vous souhaitez l'utiliser en tant que fonction get_or_create, vous pouvez peut-être gérer le problème en renvoyant l'objet utilisateur existant.
Cela dit, c'est peut-être un problème pour votre application, auquel cas vous souhaitez mettre le gestionnaire d'exceptions autour du code qui a appelé votre fonction utilisateur create et laisser la fonction appelante déterminer comment y faire face, par exemple, en demandant l'utilisateur à entrer un autre nom d'utilisateur, ou tout ce qui a du sens pour votre application.
la source