I'm in a location with poor Internet access. In order to ensure that a call to an external service succeeds, I am wrapping the call in a pseudo-do-while in Python. Additionally, I am limiting the call to running a maximum of three times:def post_safe(url, params):    done = 0    max_tries = 3    messages = []    while done<max_tries:        try:            response = requests.post(url, data=params)        except Exception as e:            messages.append(e)            time.sleep(1)        else:            done = max_tries+1        done += 1    if done==max_tries:        output = %s\n % (datetime.now().strftime('%Y-%m-%d %H:%M'),)        output+= requests() failed 3 times:\n        for m in messages:            output+= m+\n        print(output)        return False    return TrueI personally am not satisfied with the 'Pythoness' of this code. It looks inelegant, and I would have preferred to use the type bool for done but that would require a second variable to count the iterations.Is there a cleaner way to achieve a do-while in Python while limiting the amount of iterations?
Do-While loop in Python, with limit on the amount of 'do's
python;error handling
The else branch in your try is hackish (skipping over the max_tries) so I added success variable.(Although you asked not to avoid it in the question, I think it's the better way, and I'll explain why.)It also nicely allowed me to replace if done==max_tries with if not success;remove else branch altogether;return success instead of having two return statements.I think it reads more easily now.def post_safe(url, params):    messages = []    success = False    max_retries = 3    retries = 0    while retries < max_retries and not success:        try:            response = requests.post(url, data=params)            success = True        except Exception as e:            messages.append(e)            time.sleep(1)        retries += 1    if not success:        output = %s\n % (datetime.now().strftime('%Y-%m-%d %H:%M'),)        output+= requests() failed 3 times:\n        for m in messages:            output+= m+\n        print(output)    return successYou can also get rid of success by returning True early in try:def post_safe(url, params):    messages = []    retries = 0    max_retries = 3    while retries < max_retries:        try:            response = requests.post(url, data=params)            return True        except Exception as e:            messages.append(e)            time.sleep(1)        retries += 1    output = %s\n % (datetime.now().strftime('%Y-%m-%d %H:%M'),)    output+= requests() failed 3 times:\n    for m in messages:        output+= m+\n    print(output)    return FalseI don't like this approach. It wins us a variable and two lines but obfuscates the flow: In which case will the last block run? When we had an if not success condition, it was obvious, but now from a quick glance it looks like this block executes every time;What are function's return points? The first example had just one, and it was obvious what the return value represented.Let me quote PEP 20:Sparse is better than dense.Readability counts.Finally, success may be an extra variable from computer's point of view, but for a human, it's the expression that determines if the last block of code runs. It's good to give it a name.