2015-10-11 13 views
84

Ho appena preso Python come mio linguaggio di scripting e sto cercando di capire come gestire correttamente gli errori con boto3.Boto3, python e come gestire gli errori

Sto cercando di creare un utente IAM:

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

Quando la chiamata a create_user riesce, ottengo un oggetto pulito che contiene il codice di stato HTTP della chiamata API ei dati del nuovo utente .

Esempio:

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

Questa grande opera. Ma quando questo fallisce (come se l'utente già esistesse), ottengo solo un oggetto di tipo botocore.exceptions.ClientError con solo testo per dirmi cosa è andato storto.

Esempio: ClientError ('Si è verificato un errore (EntityAlreadyExists) quando si chiama l'operazione CreateUser:. Esiste un utente con nome già omesso',)

Questa (AFAIK) rende molto difficile la manipolazione errore perché non posso è sufficiente attivare il codice di stato HTTP risultante (409 per l'utente già esistente in base ai documenti API AWS per IAM). Questo mi fa pensare che devo fare qualcosa nel modo sbagliato. Il modo ottimale sarebbe che boto3 non generasse mai eccezioni, ma juts restituisce sempre un oggetto che riflette come è andata la chiamata all'API.

Qualcuno può illuminarmi su questo tema o indicarmi la giusta direzione?

Grazie mille!

+1

Documenti AWS http://botocore.readthedocs.io/en/latest/client_upgrades.html#error-handling –

risposta

177

Utilizzare la risposta contenuta all'interno dell'eccezione. Ecco un esempio:

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 

Il dict risposta nel eccezione conterrà il seguente:

  • ['Error']['Code'] esempio "EntityAlreadyExists" o "ValidationError"
  • ['ResponseMetadata']['HTTPStatusCode'] ad es. 400
  • ['ResponseMetadata']['RequestId'] ad es. 'd2b06652-88d7-11e5-99d0-812348583a35'
  • ['Error']['Message'] ad es. "Si è verificato un errore (EntityAlreadyExists) ..."
  • ['Error']['Type'] ad es. 'Mittente'

Per ulteriori informazioni, vedere botocore error handling.

[Aggiornamento: 2018/03/07]

L'AWS Python SDK ha iniziato a esporre le eccezioni di servizio sulla clients (anche se non in resources) che è possibile in modo esplicito prendere, quindi è ora possibile scrivere codice simile a questo:

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 

Sfortunatamente, non esiste attualmente alcuna documentazione per queste eccezioni.

-2

È necessario eseguire un'operazione quando non riesce a gestire il problema. In questo momento stai restituendo l'eccezione vera e propria. Ad esempio, se non è un problema che l'utente esiste già e si desidera utilizzarlo come funzione get_or_create, è possibile gestire il problema restituendo l'oggetto utente esistente.

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. 

Detto questo, forse è un problema per la vostra applicazione, nel qual caso si desidera a voler mettere il gestore di eccezioni attorno al codice che ha chiamato il vostro creare funzione utente e lasciare che la funzione di chiamata a determinare come affrontare ad esempio, chiedendo all'utente di inserire un altro nome utente o qualsiasi altra cosa abbia senso per la propria applicazione.

+0

Ma l'utente esiste già è solo uno dei modi in cui la chiamata API può non riuscire. Non vedo un modo per differenziare tra questi con questo metodo. – SQDK

+0

Solo dimostrando come funziona la gestione delle eccezioni a livello di base, perché sembra che si tratti della confusione. Ho inserito un commento in tal senso. – tlastowka

+0

Grazie per quello. Questo non fa altro che rafforzare il mio sospetto che questa domanda sia più specifica di boto3 che specifica per Python. Non sono a conoscenza di schemi comuni per la gestione degli errori in Python, quindi il mio modo generico di porre la domanda – SQDK

0

Oppure un confronto sul nome della classe, ad es.

Poiché vengono creati dinamicamente, non è possibile importare la classe e acquisirla utilizzando Python reale.

+0

Quindi vorrei prendere tutte le eccezioni con 'except Exception as e' e quindi avere if istruzioni per determinare l'eccezione specifica? In che modo è diverso/migliore rispetto ad osservare eccezioni specifiche? Le sue più linee, e avresti bisogno di importare la libreria per ottenere comunque il nome della classe. A meno che non vogliate usare hardcoding il nome dell'eccezione. Tutto sommato, sembra un brutto modo di procedere. – SQDK

+0

@SQDK scusa la mia risposta non è chiara, ma non di cosa stai parlando. L'ho aggiornato. – jmoz