Write a while loop that polls until a condition is met, with a safety counter so the loop cannot run forever.
A while loop repeats its body for as long as the condition stays true. The condition is checked again before every pass, so anything that you change inside the body can end the loop. That is exactly what makes it the right tool for polling, for retrying, and for reading a stream whose length you do not know.
attempts = 0
max_attempts = 5
result = None
while attempts < max_attempts:
attempts += 1
print('attempt', attempts)
if attempts == 3:
result = 'connected'
break
print(result, 'after', attempts, 'attempts')
The output is attempt 1, attempt 2, attempt 3, and then connected after 3 attempts. The loop leaves through the break, so the counter never reaches five.
The safety counter is the habit worth forming. A while loop whose condition depends on something outside your control, such as a network call or a queue, can spin forever if the condition never becomes true. Bounding the number of attempts turns an endless hang into a failure that you handle, and it costs you one extra line.
The same reasoning applies to the classic loop that validates input. You keep asking while the answer is not acceptable, and in that shape a while loop is better than a for loop, because the number of repetitions is genuinely unknown.
Use a for loop instead whenever you know how many rounds you need, such as when you are walking through a list, a range, the lines of a file, or any other iterable. A for loop cannot be left in an endless state by a mistake in its body, and it reads more directly.