it-swarm.com.de

Boto3, python und wie man mit Fehlern umgeht

Ich habe gerade python als meine bevorzugte Skriptsprache ausgewählt und versuche herauszufinden, wie man mit boto3 richtig mit Fehlern umgeht.

Ich versuche, einen IAM-Benutzer zu erstellen:

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

Wenn der Aufruf von create_user erfolgreich ist, erhalte ich ein ordentliches Objekt, das den http-Statuscode des API-Aufrufs und die Daten des neu erstellten Benutzers enthält.

Beispiel:

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

Das funktioniert super. Aber wenn dies fehlschlägt (als ob der Benutzer bereits existiert), erhalte ich nur ein Objekt vom Typ botocore.exceptions.ClientError mit nur Text, um mir mitzuteilen, was schief gelaufen ist.

Beispiel: ClientError ('Beim Aufrufen der CreateUser-Operation ist ein Fehler aufgetreten (EntityAlreadyExists): Benutzer mit weggelassenem Namen ist bereits vorhanden.',)

Dies (AFAIK) macht die Fehlerbehandlung sehr schwierig, da ich den resultierenden http-Statuscode nicht einfach einschalten kann (409 für Benutzer ist gemäß den AWS API-Dokumenten für IAM bereits vorhanden). Das lässt mich denken, dass ich etwas falsch machen muss. Der optimale Weg wäre, dass boto3 niemals Ausnahmen auslöst, aber juts immer ein Objekt zurückgibt, das die Funktionsweise des API-Aufrufs widerspiegelt.

Kann mich jemand aufklären oder in die richtige Richtung weisen?

Danke vielmals!

156
SQDK

Verwenden Sie die in der Ausnahme enthaltene Antwort. Hier ist ein Beispiel:

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)

Das Antwortdikt in der Ausnahme enthält Folgendes:

  • ['Error']['Code'] z.B. "EntityAlreadyExists" oder "ValidationError"
  • ['ResponseMetadata']['HTTPStatusCode'] z.B. 400
  • ['ResponseMetadata']['RequestId'] z.B. 'd2b06652-88d7-11e5-99d0-812348583a35'
  • ['Error']['Message'] z.B. "Ein Fehler ist aufgetreten (EntityAlreadyExists) ..."
  • ['Error']['Type'] z.B. 'Absender'

Weitere Informationen finden Sie unter Botocore-Fehlerbehandlung .

[Aktualisiert: 2018-03-07]

Das AWS Python SDK hat damit begonnen, Dienstausnahmen für Clients (jedoch nicht für Ressourcen ) verfügbar zu machen, die Sie explizit abfangen können Jetzt ist es möglich, diesen Code so zu schreiben:

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)

Leider gibt es derzeit keine Dokumentation für diese Ausnahmen.

334
jarmod

Nur eine Aktualisierung des Problems "Keine Ausnahmen bei den Ressourcen", auf das @jarmod hingewiesen hat (Sie können Ihre Antwort jederzeit aktualisieren, wenn das Folgende zutrifft).

Ich habe den folgenden Code getestet und er läuft einwandfrei. Es benutzt 'resources' für doing Dinge, fängt aber das client.exceptions - obwohl es etwas falsch 'aussieht' ... es testet gut, die Ausnahmeklassen werden angezeigt und passen zusammen, wenn man sich mit der Verwendung des Debuggers zur Ausnahmeszeit befasst ...

Es ist möglicherweise nicht auf alle Ressourcen und Clients anwendbar, funktioniert jedoch für Datenordner (auch bekannt als S3-Buckets).

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

Hoffe das hilft...

12
R. Simac

Ich fand es sehr nützlich, da die Ausnahmen nicht dokumentiert sind, um alle Ausnahmen auf dem Bildschirm für dieses Paket aufzulisten. Hier ist der Code, mit dem ich es gemacht habe:

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

Was in ... endet:

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
7
jamescampbell

Oder ein Vergleich des Klassennamens, z.

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

Da sie dynamisch erstellt werden, können Sie die Klasse niemals mit echtem Python importieren und abfangen.

2
jmoz

Wenn Sie die Anmelde-API (AWS Cognito) mit Python3 aufrufen, können Sie den folgenden Code verwenden.

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'] ist InvalidPasswordException, UsernameExistsException usw. In der Hauptfunktion oder dort, wo Sie die Funktion aufrufen, können Sie die Logik schreiben, um dem Benutzer eine aussagekräftige Nachricht zukommen zu lassen.

Ein Beispiel für die Antwort (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
  }
}

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

0
Haris Np