Eu estou tentando descobrir como fazer o tratamento adequado de erros com o boto3.
Estou tentando criar um usuário do IAM:
def create_user(username, iam_conn):
try:
user = iam_conn.create_user(UserName=username)
return user
except Exception as e:
return e
Quando a chamada para create_user é bem-sucedida, recebo um objeto puro que contém o código de status http da chamada da API e os dados do usuário recém-criado.
Exemplo:
{'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'
}
}
Isso funciona muito bem. Mas quando isso falha (como se o usuário já existisse), apenas obtive um objeto do tipo botocore.exceptions.ClientError com apenas texto para me dizer o que deu errado.
Exemplo: ClientError ('Ocorreu um erro (EntityAlreadyExists) ao chamar a operação CreateUser: O usuário com o nome omitido já existe.',)
Isso (AFAIK) dificulta muito o tratamento de erros, porque não posso simplesmente ativar o código de status http resultante (409 para o usuário já existe, de acordo com os documentos da API da AWS para IAM). Isso me faz pensar que devo estar fazendo algo da maneira errada. A melhor maneira seria o boto3 nunca lançar exceções, mas juts sempre retornam um objeto que reflete como foi a chamada da API.
Alguém pode me esclarecer sobre esse assunto ou me indicar a direção certa?
Respostas:
Use a resposta contida na exceção. Aqui está um exemplo:
O ditado de resposta na exceção conterá o seguinte:
['Error']['Code']
por exemplo, 'EntityAlreadyExists' ou 'ValidationError'['ResponseMetadata']['HTTPStatusCode']
por exemplo, 400['ResponseMetadata']['RequestId']
por exemplo, 'd2b06652-88d7-11e5-99d0-812348583a35'['Error']['Message']
por exemplo, "Ocorreu um erro (EntityAlreadyExists) ..."['Error']['Type']
por exemplo, "Remetente"Para obter mais informações, consulte Tratamento de erros de botocore .
[Atualizado em: 07-03-2018]
O AWS Python SDK começou a expor exceções de serviço em clientes (embora não em recursos ) que você pode capturar explicitamente; portanto, agora é possível escrever esse código da seguinte maneira:
Infelizmente, atualmente não há documentação para essas exceções.
fonte
200
na sua verificação, pois o código de retorno pode ser um2xx
código de status HTTP diferente (por exemplo,204
ao excluir um cofre ou archive,201
ao criar, etc.). Na melhor das hipóteses, deve-se procurar um código que não seja 4xx (por exemplo,statusCode < 400
) , mas isso é realmente quebradiço e eu não o recomendaria de qualquer maneira: é melhor confiar emboto
lançar exceções no seu código.Achei muito útil, uma vez que as exceções não estão documentadas, listar todas as exceções na tela deste pacote. Aqui está o código que eu costumava fazer:
O que resulta em:
fonte
Apenas uma atualização para o problema 'sem exceções de recursos', conforme apontado por @jarmod (sinta-se à vontade para atualizar sua resposta, se abaixo parecer aplicável)
Testei o código abaixo e ele funciona bem. Ele usa 'recursos' para fazer as coisas, mas captura o
client.exceptions
- embora 'pareça' um pouco errado ... ele testa bem, as classes de exceção são mostradas e correspondentes quando analisadas no uso do depurador no momento da exceção ...Pode não ser aplicável a todos os recursos e clientes, mas funciona para pastas de dados (também conhecidas como s3 buckets).
Espero que isto ajude...
fonte
s3.meta.client.exceptions.NoSuchBucket
s3
é o recurso de serviço, por exemplos3 = boto3.resource('s3')
. Funciona também para os recursos reais, como baldes:boto3.resource('s3').Bucket('bucket-name').meta.client.exceptions. ...
Como alguns outros já mencionados, você pode detectar certos erros usando o cliente de serviço (
service_client.exceptions.<ExceptionClass>
) ou o recurso (service_resource.meta.client.exceptions.<ExceptionClass>
), no entanto, não está bem documentado (também quais exceções pertencem a quais clientes). Então, aqui está como obter o mapeamento completo no momento da redação (janeiro de 2020) na região UE (Irlanda) (eu-west-1
):Aqui está um subconjunto do documento bastante grande:
fonte
Ou uma comparação com o nome da classe, por exemplo
Como eles são criados dinamicamente, você nunca pode importar a classe e capturá-la usando o Python real.
fonte
except Exception as e
e, em seguida, tenho instruções para determinar a exceção específica? Como isso é diferente / melhor do que capturar exceções específicas? É mais linhas, e você precisaria importar a biblioteca para obter o nome da classe de qualquer maneira. A menos que você queira codificar o nome da exceção. Em suma, parece uma maneira ruim de fazer isso.Se você estiver chamando a API de inscrição (AWS Cognito) usando Python3, poderá usar o código a seguir.
error.response ['Error'] ['Code'] será InvalidPasswordException, UsernameExistsException etc. Portanto, na função principal ou onde você está chamando a função, você pode escrever a lógica para fornecer uma mensagem significativa ao usuário.
Um exemplo para a resposta (error.response):
Para referência adicional: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.sign_up
fonte
Caso você precise lidar com o
logs
cliente indiscutivelmente hostil ( CloudWatch Logsput-log-events
), é isso que eu tenho que fazer para capturar corretamente as exceções do cliente Boto3:Isso funciona tanto na primeira tentativa (com LogStream vazio) quanto nas subsequentes.
fonte
Após a atualização do @ armod sobre as exceções sendo adicionadas diretamente aos
client
objetos. Vou mostrar como você pode ver todas as exceções definidas para sua classe de cliente.Exceções são geradas dinamicamente quando você cria seu cliente com
session.create_client()
ouboto3.client()
. Internamente, ele chama métodobotocore.errorfactory.ClientExceptionsFactory._create_client_exceptions()
e preenche oclient.exceptions
campo com classes de exceção construídas.Todos os nomes de classe estão disponíveis no
client.exceptions._code_to_exception
dicionário, para que você possa listar todos os tipos com o seguinte snippet:Espero que ajude.
fonte
Você precisa fazer algo quando não conseguir lidar com o problema. Agora você está retornando a exceção real. Por exemplo, se o usuário já não é um problema e você deseja usá-lo como uma função get_or_create, talvez você lide com o problema retornando o objeto de usuário existente.
Dito isso, talvez seja um problema para o seu aplicativo. Nesse caso, você deseja colocar o manipulador de exceção em torno do código que chamou sua função de usuário create e deixar a função de chamada determinar como lidar com ele, por exemplo, perguntando o usuário insira outro nome de usuário ou o que fizer sentido para seu aplicativo.
fonte