Search code examples
pythonpython-requeststry-except

Simplify try/except with more than one except


I have try/except block which handles API requests to some client.

 while attempts < 10:
    try: 
        r = requests.post(server, data=contents,
                          auth=HTTPBasicAuth(service_userid, service_pswd))
        r.raise_for_status()
    except requests.exceptions.HTTPError as errh:
        print ('Http Error:',errh)
        attempts += 1  
        if attempts == 10: 
            body = 'Http Error: ' + str(errh)
            subject = 'Failure'
            sendEmailMessage(SMPTHOST, fromEmailAddr, toEmailAddr, subject, body)
    except requests.exceptions.ConnectionError as errc:
        print ('Error Connecting:',errc)
        attempts += 1  
        if attempts == 10: 
            body = 'Error Connecting: ' + str(errh)
            subject = 'Failure'
            sendEmailMessage(SMPTHOST, fromEmailAddr, toEmailAddr, subject, body)
    except requests.exceptions.Timeout as errt:
        print ('Timeout Error:',errt)
        attempts += 1  
        if attempts == 10: 
            body = 'Timeout Error: ' + str(errh)
            subject = 'Failure'
            sendEmailMessage(SMPTHOST, fromEmailAddr, toEmailAddr, subject, body)
    except requests.exceptions.RequestException as err:
        print ('Unidentified error: ',err)
        attempts += 1  
        if attempts == 10: 
            body = 'Unidentified error: ' + str(errh)
            subject = 'Failure'
            sendEmailMessage(SMPTHOST, fromEmailAddr, toEmailAddr, subject, body)

How can I simplify above code? In general, I would like to handle HTTP response error codes. I want to send an e-mail with specific error information only in case I get at least 10 error codes for the same call.


Solution

  • Since the action to perform is the same in each case, just group the exceptions into a single one, then customize the messages according to the error class / class name:

        except (requests.exceptions.HTTPError,requests.exceptions.ConnectionError,requests.exceptions.RequestException,requests.exceptions.Timeout) as err:
            error_message = "{}: ".format(err.__class__.__name__,err)
            print (error_message)
            attempts += 1  
            if attempts == 10: 
                body = error_message
                subject = 'Failure'
                sendEmailMessage(SMPTHOST, fromEmailAddr, toEmailAddr, subject, body)
    

    If you need an indirection, just create a dictionary class name => string/action to perform/whatever.