将重试循环嵌套到 try except 块中 python API

nesting a retry loop into a try except block python API

我有以下 try except 块对我很有效:

try:
    r = requests.post(endpoint,data=json.dumps(report_params),headers=headers)
    r.raise_for_status()
except requests.exceptions.HTTPError as errhttp:
    print ("Http Error:",errhttp)
    mbody = "The process encountered the following HTTP error: " + str(errhttp)
    sendmail(fromaddr, toaddr, msubject, mbody)
except requests.exceptions.ConnectionError as errconn:
    print ("Error Connecting:",errconn)
    mbody = "The process encountered the following connection error: " + str(errconn)
    sendmail(fromaddr, toaddr, msubject, mbody)
except requests.exceptions.Timeout as errtimeout:
    print ("Timeout Error:",errtimeout)
    mbody = "The process timed out after 3 tries and gave the error: " + str(errtimeout)
    sendmail(fromaddr, toaddr, msubject, mbody)
except requests.exceptions.RequestException as err:
    print ("No idea what the hell happened",err)
    mbody = "The process encountered the following unexpected error: " + str(err)
    sendmail(fromaddr, toaddr, msubject, mbody)

我想添加一个重试循环或函数,在出现连接错误或超时错误时重试 3 次

我在 SO 上找到了一些应该有效的东西:

tries = 3
for i in range(tries):
    try:
        do_the_thing()
    except KeyError as e:
        if i < tries - 1: # i is zero indexed
            continue
        else:
            raise
    break

我仍在学习 try except 块,因此不太擅长它们。我怎么能把类似循环的东西放在上面的块中,让它看起来像这样:

try:
    r = requests.post(endpoint,data=json.dumps(report_params),headers=headers)
    r.raise_for_status()
except requests.exceptions.HTTPError as errhttp:
    print ("Http Error:",errhttp)
    mbody = "The process encountered the following HTTP error: " + str(errhttp)
    sendmail(fromaddr, toaddr, msubject, mbody)
except requests.exceptions.ConnectionError as errconn:

#### RETRY 3 TIMES AND IF SUCCESSFUL, CONTINUE TO NEXT EXCEPT STATEMENT.  IF UNSUCCESSFUL, SEND THE EMAIL

    print ("Error Connecting:",errconn)
    mbody = "The process failed to connect after 3 tries and gave the following error: " + str(errconn)
    sendmail(fromaddr, toaddr, msubject, mbody)
except requests.exceptions.Timeout as errtimeout:

#### RETRY 3 TIMES AND IF SUCCESSFUL, CONTINUE TO NEXT EXCEPT STATEMENT.  IF UNSUCCESSFUL, SEND THE EMAIL

    print ("Timeout Error:",errtimeout)
    mbody = "The process timed out after 3 tries and gave the error: " + str(errtimeout)
    sendmail(fromaddr, toaddr, msubject, mbody)
except requests.exceptions.RequestException as err:
    print ("No idea what the hell happened",err)
    mbody = "The process encountered the following unexpected error: " + str(err)
    sendmail(fromaddr, toaddr, msubject, mbody)

谢谢!

对于 ConnectionError 和 Timeout,将 try/except 包装在 while 循环中,并在 except 子句中跟踪 tries 的次数。 return 如果成功则返回结果,如果达到限制则重新引发异常。将所有这些都放在一个函数中。

def retry(max_tries=3):
    n = 0
    while True:
        try:
            r = requests.post(endpoint,data=json.dumps(report_params),headers=headers)
            r.raise_for_status()
            return r
        except (ConnectionError,Timeout) as err:
            n += 1
            if n < max_tries:
                continue
            raise 

要使用它,请在 try/except 块中调用该函数。在 except 子句中,根据引发的异常类型制作消息。

try:
    r = retry()
except (HTTPError,RequestException,ConnectionError,Timeout) as err:
    print(err)
    # craft a message based on type of error:
    if isinstance(err,ConnectionError):
        # msg = ...
        pass
    elif isinstance(err,Timeout):
        # msg = ...
        pass
    elif isinstance(err,HTTPError):
        # msg = ...
        pass
    if isinstance(err,RequestException):
        # msg = ...
        pass

或者您可能希望将所有消息制作都放入函数中。

class Special(Exception):
    pass

def retry(max_tries=3):
    n = 0
    msg = ''
    while True:
        try:
            r = requests.post(endpoint,data=json.dumps(report_params),headers=headers)
            r.raise_for_status()
            return r
        except (ConnectionError,Timeout) as err:
            # three tries
            n += 1
            if n < max_tries:
                continue
            # craft a message based on type of error:
            if isinstance(err,ConnectionError):
                msg = f'{type(err)} occurred: {str(err)}'
                pass
            elif isinstance(err,Timeout):
                # msg = ...
                pass
            raise
        except (HTTPError,RequestException) as err:
            # craft a message based on type of error:
            if isinstance(err,HTTPError):
                # msg = ...
                pass
            if isinstance(err,RequestException):
                # msg = ...
                pass
        finally:
            raise Special(msg)
    

让使用更简单

try:
    r = retry()
except Special as err:
    print(err.args)
    # send email with err.args

灵感来自于:
is there a pythonic way to try something up to a maximum number of times?

Python: Try three times a function until all failed