How to use 'while True' in Python

Learn how to use while True in Python. Explore different methods, real-world applications, common errors, and debugging tips.

How to use 'while True' in Python
Published on: 
Tue
Mar 3, 2026
Updated on: 
Wed
Apr 1, 2026
The Replit Team

The while True loop in Python creates an infinite loop that runs until explicitly stopped. It's a powerful construct for tasks that must operate continuously, like servers or event listeners.

In this article, we'll explore techniques and real-world applications for this loop. You'll also get practical tips and clear advice to debug common issues, which will help you use while True with confidence in your projects.

Using while True loops in Python

while True:
user_input = input("Enter 'quit' to exit: ")
if user_input.lower() == 'quit':
break
print(f"You entered: {user_input}")--OUTPUT--Enter 'quit' to exit: hello
You entered: hello
Enter 'quit' to exit: python
You entered: python
Enter 'quit' to exit: quit

The code above uses a while True loop to create a simple command-line prompt. This structure is perfect for applications that need to run continuously, waiting for user interaction without a predetermined number of iterations. It keeps the program active and responsive.

The key to managing this infinite loop is the exit condition. Inside the loop, an if statement checks if the user's input is 'quit'. If it is, the break statement is triggered, which immediately terminates the loop and prevents it from running indefinitely.

Common loop control techniques

Beyond simply stopping the loop with break, you can manage its flow more precisely with statements like continue and by building robust user input handlers.

Using break and continue statements

counter = 0
while True:
counter += 1
if counter % 2 == 0: # Skip even numbers
continue
print(counter)
if counter >= 5:
break--OUTPUT--1
3
5

In this example, continue and break give you precise control over the loop's execution. The loop increments a counter and uses control statements to manage what gets printed and when to stop.

  • The continue statement skips the current iteration if counter is an even number, so only odd numbers are printed.
  • The break statement stops the loop entirely when counter is greater than or equal to 5, preventing it from running forever.

Handling user input with validation

while True:
try:
number = int(input("Enter a number: "))
result = 100 / number
print(f"100 divided by {number} is {result}")
break
except ValueError:
print("Please enter a valid number.")
except ZeroDivisionError:
print("Cannot divide by zero.")--OUTPUT--Enter a number: abc
Please enter a valid number.
Enter a number: 0
Cannot divide by zero.
Enter a number: 25
100 divided by 25 is 4.0

This code uses a try...except block to make the input process bulletproof. The while True loop won't stop until you provide valid input, preventing crashes from unexpected entries.

  • The except ValueError block handles cases where the input isn't a number.
  • The except ZeroDivisionError catches attempts to divide by 0.

Only when the try block runs without any errors does the break statement execute, ending the loop.

Creating interactive menus

while True:
print("\nMenu:")
print("1. Say Hello")
print("2. Count to 3")
print("3. Exit")
choice = input("Enter your choice (1-3): ")

if choice == '1':
print("Hello, World!")
elif choice == '2':
for i in range(1, 4):
print(i)
elif choice == '3':
print("Goodbye!")
break
else:
print("Invalid choice, try again.")--OUTPUT--Menu:
1. Say Hello
2. Count to 3
3. Exit
Enter your choice (1-3): 1
Hello, World!

Menu:
1. Say Hello
2. Count to 3
3. Exit
Enter your choice (1-3): 3
Goodbye!

A while True loop is perfect for building interactive menus. The loop continuously presents a list of options and then waits for you to enter a choice. An if/elif/else block then directs the program based on your input.

  • If you enter '1' or '2', the corresponding action runs, and the menu reappears for another selection.
  • Choosing '3' triggers the break statement, which cleanly exits the loop.
  • Any other input is caught by the else block, which prompts you to try again.

Advanced loop techniques

Moving beyond simple menus and input validation, while True loops unlock advanced capabilities like performance timers, efficient data generation, and concurrent programming with threads.

Implementing timers and benchmarks

import time

start_time = time.time()
counter = 0
while True:
counter += 1
if counter >= 1000000:
break
print(f"Counted to 1 million in {time.time() - start_time:.4f} seconds")--OUTPUT--Counted to 1 million in 0.0612 seconds

You can use a while True loop to benchmark how long a piece of code takes to run. This example measures the time it takes to count to one million. It works by capturing the start time with time.time() right before the loop begins.

  • The loop runs continuously, incrementing the counter variable in each iteration.
  • When counter reaches one million, the break statement stops the loop.

Finally, the total execution time is calculated by subtracting the start time from the current time, giving you a simple performance metric.

Using while True with generators

def infinite_sequence():
num = 0
while True:
yield num
num += 1

gen = infinite_sequence()
for _ in range(5):
print(next(gen))--OUTPUT--0
1
2
3
4

A while True loop inside a generator function, like infinite_sequence(), creates an endless stream of data without hogging memory. The function doesn't run all at once. Instead, it pauses and waits for the next value to be requested.

  • The yield keyword is what makes this possible. It returns the current value of num and freezes the function's state.
  • When next(gen) is called again, the loop resumes right where it left off, increments num, and yields the next number.

This lets you work with potentially infinite sequences in a controlled, memory-efficient way.

Threading with controllable infinite loops

import threading
import time

stop_flag = threading.Event()

def background_task():
while not stop_flag.is_set():
print("Working...", end="\r")
time.sleep(0.5)
print("Background task stopped.")

thread = threading.Thread(target=background_task)
thread.start()
time.sleep(2) # Let it run for 2 seconds
stop_flag.set()
thread.join()--OUTPUT--Working...
Background task stopped.

This example runs a while loop in a separate thread, allowing a task to operate in the background without freezing the main program. It's a clean way to manage long-running services or workers that you need to control from another part of your application.

  • A threading.Event object, here named stop_flag, acts as a simple, thread-safe switch.
  • The loop runs as long as the flag isn't set, checking the condition while not stop_flag.is_set().
  • The main thread stops the loop by calling stop_flag.set(), and thread.join() waits for it to finish completely.

Move faster with Replit

Replit is an AI-powered development platform where all Python dependencies pre-installed, so you can skip setup and start coding instantly. Instead of piecing together techniques, you can use Agent 4 to build complete applications directly from a description.

Describe the app you want to build, and Agent 4 will take it from an idea to a working product. You can create tools like:

  • An interactive command-line calculator that validates your input and solves expressions in a continuous loop.
  • A background service that runs indefinitely to monitor a website's status and logs uptime.
  • A real-time data simulator that generates an endless stream of events for testing a dashboard.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

While powerful, while True loops can introduce common issues like index errors and high CPU usage if not managed carefully.

Preventing index errors with proper bounds checking in while True loops

An IndexError occurs when you try to access an item in a list or other sequence at a position that doesn't exist. In a while True loop, this can happen if you're incrementing an index without checking whether it has exceeded the collection's size. The loop will continue running, but your program will crash as soon as the index goes out of bounds.

To prevent this, always validate the index against the length of the sequence before attempting to access an element. A simple check, such as ensuring your index variable is less than the length of the list, ensures your loop can handle collections of any size without failing unexpectedly.

Reducing CPU usage with time.sleep() in polling loops

A while True loop that continuously checks for a condition without any pause will run as fast as possible, consuming 100% of a CPU core. This is inefficient and can slow down your entire system, especially for background tasks that don't need to run at maximum speed.

You can solve this by adding time.sleep() inside your loop. This function pauses the loop's execution for a specified number of seconds, yielding control back to the operating system. Even a tiny pause—like time.sleep(0.1)—dramatically reduces CPU usage, making your application more efficient and responsive.

Ensuring loop variables are properly updated in while True loops

One of the most common mistakes is creating a truly infinite loop by accident. This often happens when the variable controlling the loop's exit condition is never updated. If your break statement depends on a counter reaching a certain value, but you forget to increment the counter, the condition will never be met.

Always double-check that the logic inside your loop progresses toward the exit condition. Whether you're incrementing a counter, processing items from a list, or waiting for a specific flag to change, make sure the loop's state is always moving forward. This ensures your program behaves as expected and can exit the loop when intended.

Preventing index errors with proper bounds checking in while True loops

An IndexError is a common pitfall when using while True to process a list. It happens when your loop tries to access an index that doesn't exist, crashing the program. This often occurs if the loop's exit condition is never met.

The sum_until_negative function below shows this in action. It's designed to sum numbers until it finds a negative one, but it will crash if the list contains only positive numbers because the index i will eventually go out of bounds.

def sum_until_negative(numbers):
total = 0
i = 0
while True:
if numbers[i] < 0: # Will cause IndexError if no negative number exists
break
total += numbers[i]
i += 1
return total

Because the loop in sum_until_negative never checks if the index i is within the list's bounds, it will crash with an IndexError on an all-positive list. See how a simple bounds check solves this.

def sum_until_negative(numbers):
total = 0
i = 0
while i < len(numbers): # Add bounds check
if numbers[i] < 0:
break
total += numbers[i]
i += 1
return total

The corrected sum_until_negative function avoids an IndexError by changing the loop condition from while True to while i < len(numbers). This simple bounds check ensures the index i never exceeds the list's size, so the loop safely stops if it reaches the end of the list without finding a negative number. It's a crucial safeguard whenever you iterate through a collection and the exit condition isn't guaranteed to be met by the data itself.

Reducing CPU usage with time.sleep() in polling loops

A while True loop is often used for polling, which involves repeatedly checking if a condition is met, like waiting for a file to appear. Without a pause, this loop runs at full speed, consuming an entire CPU core and slowing your system down. The wait_for_file function below demonstrates this problem. It polls for a file's existence but does so inefficiently, causing the CPU to work much harder than it needs to.

import os
import time

def wait_for_file(filename, timeout=30):
start_time = time.time()
while True:
if os.path.exists(filename):
return True
if time.time() - start_time > timeout:
return False
# CPU is running at 100% while checking

The wait_for_file function’s loop runs without any delay, causing it to check for the file nonstop and max out the CPU. See how the corrected version below solves this with a small but crucial addition.

import os
import time

def wait_for_file(filename, timeout=30):
start_time = time.time()
while True:
if os.path.exists(filename):
return True
if time.time() - start_time > timeout:
return False
time.sleep(0.5) # Reduce CPU usage while waiting

The corrected wait_for_file function fixes the high CPU issue by adding time.sleep(0.5). This simple line pauses the loop for half a second with each check, which stops it from running at full speed and consuming all available resources.

You should use this technique in any polling loop that repeatedly checks for a condition—like waiting for a file to appear or a network service to respond. It makes your application far more efficient by yielding processing time back to the system.

Ensuring loop variables are properly updated in while True loops

It's easy to create an accidental infinite loop if you forget to update the variable controlling your exit condition. If the break statement's condition is never met, the loop runs forever. The find_all_occurrences function below demonstrates this exact problem.

def find_all_occurrences(text, char):
positions = []
i = 0
while True:
pos = text.find(char, i)
if pos == -1:
break
positions.append(pos)
# Forgot to update i, causing infinite loop
return positions

In find_all_occurrences, the search index i is never updated. The loop continuously finds the first occurrence of char from the same starting point, creating an endless cycle. The corrected version below shows how to fix this.

def find_all_occurrences(text, char):
positions = []
i = 0
while True:
pos = text.find(char, i)
if pos == -1:
break
positions.append(pos)
i = pos + 1 # Move past the found character
return positions

The corrected find_all_occurrences function avoids an infinite loop by updating its search index with i = pos + 1. This moves the starting point for the next text.find() call just past the character that was found. Without this update, the loop would repeatedly find the same first character and never terminate. Always ensure your loop variables are updated to progress toward the exit condition, especially when the loop's state doesn't change automatically.

Real-world applications

Beyond debugging, these controlled while True loops are the backbone of many real-world systems, including file monitors and services with retry logic.

File monitoring for changes with while True

A while True loop is perfect for building a file watcher that continuously checks for modifications, allowing your application to react to changes in real time.

import os
import time

file_path = "data.txt"
last_modified = os.path.getmtime(file_path) if os.path.exists(file_path) else 0

while True:
if os.path.exists(file_path):
current_modified = os.path.getmtime(file_path)
if current_modified > last_modified:
print(f"File changed at {time.ctime(current_modified)}")
last_modified = current_modified
time.sleep(1)
# This would run forever in a real application
# Adding a counter for demonstration
break

This code creates a simple file watcher. It begins by storing the initial modification time of data.txt in the last_modified variable. The while True loop then runs continuously to monitor the file for any changes.

  • Inside the loop, it gets the file's current modification time and compares it to the stored last_modified time.
  • If the file has been updated, it prints a notification and updates last_modified to the new time.
  • The time.sleep(1) call pauses the loop for one second, which prevents it from consuming excessive CPU resources.

Implementing retry logic with exponential backoff

When you're dealing with operations that can fail intermittently, like network requests, a while True loop is perfect for building a retry system with exponential backoff—a strategy that increases the delay between each attempt to avoid overwhelming a service.

import time
import random

def request_with_retry(url):
max_retries = 5
retry_count = 0
base_delay = 1 # seconds

while True:
try:
print(f"Attempting request to {url}...")
# Simulate network request with potential failure
if random.random() < 0.7: # 70% chance of failure
raise ConnectionError("Network error")

print("Request successful!")
return "Response data"
except ConnectionError as e:
retry_count += 1
if retry_count > max_retries:
print(f"Max retries reached. Giving up.")
raise

delay = base_delay * (2 ** (retry_count - 1)) + random.uniform(0, 1)
print(f"Retry {retry_count}/{max_retries} after {delay:.2f}s")
time.sleep(delay)

# Example usage (would normally throw an exception eventually)
try:
request_with_retry("https://api.example.com/data")
except ConnectionError:
print("Failed to connect after multiple attempts")

The request_with_retry function uses a while True loop to create a robust request handler. Inside the loop, a try block attempts the request. If it fails with a ConnectionError, the except block increments retry_count and calculates a longer wait time for the next attempt.

  • The loop only breaks in two ways: a successful request triggers a return, or the function gives up after max_retries.
  • Adding a random value to the delay—a technique called jitter—helps prevent multiple retries from happening at the same time.

Get started with Replit

Put these techniques into practice with Replit Agent. Describe what you want to build, like “a command-line calculator that runs in a loop” or “a service that monitors a website for changes.”

It'll handle writing the code, testing for errors, and deploying the final app. Start building with Replit and see your project come together.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.