How to use 'assert' in Python

Master Python's assert statement. This guide covers various uses, practical tips, real-world applications, and how to debug common errors.

Published on: 
Tue
Feb 24, 2026
Updated on: 
Mon
Apr 6, 2026
The Replit Team

The assert statement in Python is a powerful debugging aid. It tests a condition and triggers an error if the condition is false, which helps you catch bugs early in development.

Here, you'll explore effective techniques and tips for the assert statement. You'll also find real-world applications and debugging advice to help you write more robust and reliable code.

Basic usage of assert

x = 10
assert x == 10
print("Assertion passed!")--OUTPUT--Assertion passed!

In this example, the assert statement checks if the variable x is equal to 10. Because the condition x == 10 evaluates to true, the program continues to the next line without interruption. This demonstrates how assertions act as internal self-checks, verifying that the program's state is exactly as you expect at a specific point.

If the condition were false, Python would have raised an AssertionError and stopped the program. This immediate failure is the core benefit of using assert—it helps you catch logical errors early, right at the source, instead of letting them cause bigger problems later on.

Common assert patterns

The assert statement is more versatile than it first appears, and a few common patterns can help you write more descriptive and effective checks.

Using assert with comparison operators

age = 25
assert age >= 18, "Must be 18 or older"
assert age <= 65, "Must be 65 or younger"
print(f"Age {age} is within valid range")--OUTPUT--Age 25 is within valid range

You can pair assert with any comparison operator, like >= or <=, to validate conditions. This example uses two assertions to confirm the age variable falls within a specific range—a common pattern for enforcing data constraints.

  • The first assert checks if age is at least 18.
  • The second verifies it's no more than 65.
  • If either condition is false, Python raises an AssertionError with the custom message you provided, making it much easier to pinpoint the problem.

Using assert with custom error messages

username = "admin"
password = "weak_password"
assert password != username, "Password cannot be the same as username"
assert len(password) >= 8, "Password must be at least 8 characters long"
print("Password validation successful")--OUTPUT--Password validation successful

Adding a custom message to your assert statement makes debugging much clearer. By including a string after the condition, you can specify exactly what went wrong when an AssertionError is raised.

  • The first assertion, assert password != username, prevents using the username as a password.
  • The second, assert len(password) >= 8, enforces a minimum password length.

If either of these conditions fails, the program stops and prints your helpful message, immediately pointing you to the source of the error.

Using assert with expressions

numbers = [1, 2, 3, 4, 5]
assert len(numbers) > 0, "List cannot be empty"
assert sum(numbers) / len(numbers) > 2, "Average must be greater than 2"
print(f"List validation passed, average: {sum(numbers) / len(numbers)}")--OUTPUT--List validation passed, average: 3.0

The assert statement isn't limited to simple variables; you can use it with entire expressions. This allows you to check conditions that involve function calls or calculations directly in one line, making your code more dynamic.

  • The first assertion uses len(numbers) > 0 to confirm the list contains items before you try to work with it.
  • The second calculates the list's average on the fly with sum(numbers) / len(numbers) and validates the result against a threshold.

This pattern is perfect for verifying data integrity right after a computation.

Advanced assert techniques

While the common patterns cover most daily use cases, assert also offers advanced capabilities for handling errors and optimizing code for production.

Using assert in try-except blocks

try:
user_input = -5
assert user_input > 0, "Input must be positive"
print("Processing positive input...")
except AssertionError as e:
print(f"Validation failed: {e}")--OUTPUT--Validation failed: Input must be positive

Wrapping an assert statement in a try...except block lets you catch the AssertionError it raises. This pattern prevents a failed assertion from crashing your program, giving you a chance to handle the validation failure gracefully.

  • In the example, the assert user_input > 0 condition fails because the input is negative.
  • The except AssertionError block catches the resulting error, allowing the program to print a helpful message instead of halting.

This technique is useful for turning a debugging check into a controlled validation step, especially when dealing with user input or external data.

Disabling assertions with -O flag

import sys
# Run with python -O script.py to disable assertions
debug_mode = not hasattr(sys, 'flags') or not sys.flags.optimize
assert debug_mode, "This assertion only runs in debug mode"
print(f"Debug mode: {debug_mode}")--OUTPUT--Debug mode: True

Assertions are primarily for development and can be disabled to optimize your code for production. When you run a script using the python -O flag, the interpreter skips all assert statements, which can slightly improve performance.

  • The code checks sys.flags.optimize to determine if this optimization flag is active.
  • As a result, the assert debug_mode statement only runs when the script is executed normally, not when the -O flag is used.

This technique lets you keep helpful debugging checks in your code without affecting its performance in a production environment.

Using assert in testing scenarios

def calculate_area(radius):
return 3.14 * radius ** 2

radius = 5
expected_area = 78.5
actual_area = calculate_area(radius)
assert abs(actual_area - expected_area) < 0.1, f"Expected {expected_area}, got {actual_area}"
print(f"Test passed: Area calculation is correct ({actual_area})")--OUTPUT--Test passed: Area calculation is correct (78.5)

The assert statement is a simple yet effective tool for writing tests directly in your code. It's perfect for verifying that your functions behave as expected without needing a full testing framework.

  • In this example, assert confirms that the calculate_area function's output is correct.
  • It checks if the difference between the actual_area and expected_area is within a small tolerance, a common practice when comparing floating-point numbers.

If the calculation were wrong, the assertion would fail and immediately flag the issue, making it a great first line of defense for catching bugs and enabling code repair.

Move faster with Replit

Learning individual techniques like the assert statement is a great start, but Replit helps you move from theory to practice faster. Replit is an AI-powered development platform where all Python dependencies are pre-installed, so you can skip the setup and start coding instantly.

Instead of just piecing together code snippets, you can build complete applications with Agent 4. It takes your description of an app and handles the rest—from writing the code and connecting to databases to deploying it live. You can go from an idea to a working product by describing what you want to build:

  • A user registration validator that uses assert to check for password strength, age restrictions, and unique usernames.
  • A data analysis script that asserts a dataset is not empty and that calculated values, like averages, are within a valid range before generating a report.
  • An automated testing utility that runs a series of assert checks to confirm a function's calculations are correct, catching bugs early.

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

Common errors and challenges

Using assert effectively means avoiding a few common pitfalls that can undermine its power and introduce bugs into your code.

Debugging reliability: Don't use assert for data validation

It’s tempting to use assert to validate user input or data from external sources, but this is a risky practice. Assertions are designed for debugging and can be completely disabled when you run a Python script with the -O (optimize) flag. If you rely on assert for validation, your checks will disappear in a production environment, leaving your application vulnerable.

For handling untrusted data, you should use explicit conditional checks that raise specific errors. This ensures your validation logic always runs, regardless of how the code is executed.

  • Instead of: assert user_age >= 18, "User must be an adult"
  • Use: if not user_age >= 18: raise ValueError("User must be an adult")

Common error: Missing or unclear assert messages

An assert statement without a message can leave you guessing when it fails. If assert is_valid(data) triggers an error, you'll only see a generic AssertionError. You won't know what condition failed or what the expected outcome was, which slows down debugging.

Always include a descriptive message that explains what went wrong. A clear message like assert is_valid(data), "Data validation failed for user ID 123" immediately points you to the problem's source, saving you valuable time and effort.

Avoiding side effects in assert expressions

Your assert statements should never change the state of your program. An expression with a "side effect"—one that modifies data—can cause major problems because the expression won't run when assertions are disabled with the -O flag. This can lead to bugs that only appear in your production environment.

For example, avoid checks like assert user_list.pop() == "admin". If assertions are disabled, the pop() method is never called, and the "admin" user is never removed from the list. Instead, perform the action first and then assert the result:

  • First, call the function: last_user = user_list.pop()
  • Then, check the outcome: assert last_user == "admin", "Last user should be admin"

This pattern ensures your program behaves consistently whether assertions are active or not.

Debugging reliability: Don't use assert for data validation

Using assert for data validation, like in a calculate_discount function, seems convenient but creates a false sense of security. Since assertions can be disabled in production, your validation logic might disappear entirely. The following code demonstrates this exact pitfall.

def calculate_discount(price, percentage):
assert 0 <= percentage <= 100, "Percentage must be between 0 and 100"
return price * (percentage / 100)

user_percentage = 150
discounted_price = calculate_discount(100, user_percentage)
print(f"Discounted price: ${discounted_price}")

Since assert is disabled in production, the calculate_discount function processes the invalid 150 percent without complaint, creating a logical bug. The corrected code below shows how to implement a reliable validation check.

def calculate_discount(price, percentage):
if not (0 <= percentage <= 100):
raise ValueError("Percentage must be between 0 and 100")
return price * (percentage / 100)

user_percentage = 150
try:
discounted_price = calculate_discount(100, user_percentage)
print(f"Discounted price: ${discounted_price}")
except ValueError as e:
print(f"Error: {e}")

The corrected calculate_discount function replaces the risky assert with a reliable if statement. This check raises a ValueError if the percentage is out of bounds, ensuring your validation logic always runs. By wrapping the function call in a try...except block, you can catch this specific error and handle it gracefully. This approach is essential for validating any data you don't control—like user input—because it works consistently in both development and production environments.

Common error: Missing or unclear assert messages

A failing assert stops your program, but it's not very helpful if you don't know why it failed. Leaving out a message turns a useful debugging tool into a vague error, forcing you to investigate the cause from scratch.

The following code demonstrates this. When the process_data function is called with an empty list, the assert triggers an error but provides no context, slowing down the fix.

def process_data(data):
assert len(data) > 0
return sum(data) / len(data)

result = process_data([])
print(f"Result: {result}")

Calling process_data with an empty list makes the assert len(data) > 0 check fail, raising a vague AssertionError. The following example shows how to provide the necessary context for faster debugging.

def process_data(data):
assert len(data) > 0, "Cannot process empty data set"
return sum(data) / len(data)

try:
result = process_data([])
print(f"Result: {result}")
except AssertionError as e:
print(f"Error: {e}")

The corrected process_data function now includes a descriptive message. When the assert fails, you see “Cannot process empty data set” instead of a generic error, which pinpoints the problem instantly. The try...except block then catches this AssertionError, preventing a program crash. This simple habit of adding clear messages to your assertions will save you significant debugging time, especially in functions with multiple checks where any one of them could fail.

Avoiding side effects in assert expressions

Your assert statements should never modify data. When an expression inside an assert has a side effect, like removing an item from a list, it creates bugs that only appear in production. The following code demonstrates this risky pattern.

users = ["Alice", "Bob", "Charlie"]
assert users.pop() == "Charlie", "Last user should be Charlie"
print(f"Remaining users: {users}")

The users.pop() call is a side effect hidden inside the assert. When assertions are disabled, the pop() method never runs, so the list isn't modified. The following example demonstrates the correct way to separate the action from the assertion.

users = ["Alice", "Bob", "Charlie"]
assert users[-1] == "Charlie", "Last user should be Charlie"
print(f"All users: {users}")

The corrected code avoids side effects by checking the list's last element with users[-1] == "Charlie" instead of calling users.pop(). This ensures the assert statement only reads data—it doesn't change it. Your program's behavior now remains consistent, whether assertions are enabled or disabled.

Be careful anytime you place a function call inside an assert expression. Always ensure it doesn't modify your program's state, as this approach is memory-efficient and prevents unexpected behavior.

Real-world applications

Beyond simple checks, assert is also valuable for verifying internal logic in larger applications, such as during form and API data handling.

Using assert for form data validation

The assert statement offers a straightforward way to verify that incoming form data meets all required conditions during the development phase.

def validate_registration_form(username, email, age):
assert len(username) >= 3, "Username must be at least 3 characters"
assert "@" in email and "." in email, "Invalid email format"
assert 13 <= age <= 120, "Age must be between 13 and 120"
return True

try:
user_data = validate_registration_form("john", "john@example.com", 25)
print("Form validation passed!")
except AssertionError as e:
print(f"Validation error: {e}")

The validate_registration_form function uses multiple assert statements to run a series of quick checks. It's a concise way to confirm that incoming data meets your expectations during development before the program continues, similar to how vibe coding enables rapid development workflows.

  • It verifies the username length is sufficient.
  • It checks for basic email structure using the in operator.
  • It confirms the age falls within a valid range.

Since the provided data is valid, all assertions pass, and the success message is printed. If any check had failed, the try...except block would catch the AssertionError and display the helpful error message you wrote.

Using assert for API response validation

You can also apply assert to API responses, giving you a simple way to verify their structure and content during development.

def validate_api_response(response):
assert response.get("status") == "success", "API call failed"
assert "data" in response, "Response missing data field"
assert isinstance(response["data"], list), "Data field must be a list"
return response["data"]

# Simulate API response
api_response = {"status": "success", "data": [{"id": 1, "name": "Product A"}]}
try:
data = validate_api_response(api_response)
print(f"Processed {len(data)} items from API")
except AssertionError as e:
print(f"API validation failed: {e}")

The validate_api_response function confirms an API response matches its expected "contract" before your code uses it. It's a quick way to guard against unexpected changes from an external service during development.

The function runs three checks:

  • It confirms the API call was successful by checking response.get("status").
  • It verifies the payload contains a "data" key.
  • It ensures the data is formatted as a list using isinstance.

If the response structure is ever different, an assertion fails, immediately flagging the issue for you.

Get started with Replit

Turn your knowledge of assert into a real tool. Describe what you want to build to Replit Agent, like “a data validator that uses assert to check API responses” or “a unit test for a calculator function.”

Replit Agent will write the code, test for errors, and deploy your application directly from your browser. Start building with Replit.

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.

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.