Python Assert Statements

In Python, the assert statements make sure a condition is met before continuing the execution of the program.

For example, let’s assert that a discounted price does not go below 0 nor surpass the original price:

def discount(price, dc):
    new_price = int(price * (1.0 - dc))

    assert 0 <= new_price, "Price is less than 0."
    assert new_price <= price, "Price is more than original price"

    return new_price

Calling this function with an input that makes the assertion fail will lead to the code crash with a clear error:

price = 125
dc = 1.3 # 130% discount

discounted_price = discount(price, dc)

print(discounted_price)

Output:

Traceback (most recent call last):
  File "example.py", line 10, in <module>
    discounted_price = discount(price, dc)
  File "example.py", line 3, in discount
    assert 0 <= new_price <= price
AssertionError: Price is less than 0.

You should only do assertions when debugging your code. Do not leave assert statements in a production environment!

In this guide, you will learn how to adapt assertion as one of your debugging routines. You are going to see some real-life use cases of assertion in Python. And you will also see an example of when assertion can be really dangerous.

Assertion in Python

Debugging Python code helps you track down bugs that cause issues in your programs.

Every developer knows how daunting the process of debugging can sometimes be.

When you debug a program, you might want to test for specific conditions. More specifically, if a condition is not met, the program should throw an error instead of continuing. This is one common way to narrow down the root cause of a bug and save time when debugging code.

Python’s built-in assert statement is the right solution for this. The assert statement is used to handle errors during the debugging phase.

You can use Python’s built-in assert statement to debug your code.

Assertion informs a developer of an unrecoverable error. Thus, the assertion is not intended to point out regular error conditions like “File not found”.

You should use assertions to declare conditions that should be impossible in your code. If one of these impossible conditions does not hold, it means there’s a bug in your code.

Asserting works so that if a condition you assert is True, the program continues. But if the condition evaluates False, an error called AssertionError is thrown.

If your program code has no bugs, these impossible conditions never become True. But if one occurs, the program crashes with an AssertionError telling you exactly which “impossible” condition was triggered.

Use Assertions Cautiously in Python

Use assertions cautiously, only when debugging your code.

Assertion helps you find the root cause of a bug. Unlike regular runtime errors in Python, assertions have to be manually defined by a developer.

Unlike traditional code errors, It is possible to completely turn off assertion statements in a Python interpreter. This can lead to problems if you rely on assertions in the code. If you have disabled assertions, the conditions checked don’t get triggered and the faulty code is able to proceed in execution.

Now that you know about the assertion in Python on a theoretical level, let’s take a look at some concrete examples.

The assert Statements in Python

The assert statement checks if a condition evaluates True.

  • If it does, the program keeps running.
  • If it does not, the program returns an AssertionError and the program stops executing.

In Python, assert is a reserved keyword. It follows this syntax:

assert condition, message

Where the two parameters are:

  • condition: the condition against which you test your code.
  • message: the message you want to show if the assertion fails. This is an optional parameter that you do not need to specify. Leave it out if you don’t need one.

Similarity to If Statements

In case you’re wondering, using assert is roughly equal to the following traditional if statement in Python:

if not condition:
    raise AssertionError(message)

One difference to this is that the assert statements can be disabled by running a Python program with an -O flag.

But the main difference is that the assert statement means checking if a condition is not True only in the debug mode.

So in reality, using the assert statement is equivalent to the following:

if __debug__:
    if not condition:
        raise AssertionError(message)

Even though this is a subtle difference, it highlights why you should only use assertion in debugging. If the __debug__ mode False, assertions do not get triggered, and the code with potential bugs is free to run.

Assert Example in Python

Let’s build a simple discount calculator in Python. This function takes a price of an item and a discount percentage as a fractional number.

Here is the code:

def discount(price, dc):
    new_price = int(price * (1.0 - dc))

    assert 0 <= new_price, "Price is less than 0."
    assert new_price <= price, "Price is more than original price"

    return new_price

In this function, the assert statements make sure:

  • The discounted price is not less than 0.
  • The discounted price is not more than the original price.

Now, let’s test how it works by calling the discount() function:

price = 125
dc = 0.3

discounted_price = discount(price, dc)

print(discounted_price)

Output:

87

So it seems to work as we intended.

Now, let’s input an invalid discount to the discount() function. As you may know from maths, it would make no sense to give a discount exceeding 100% (or 1.0 when talking about fractional discounts).

Let’s see what happens with a discount of over 100%.

For example, let’s say the discount is 130% (1.3 in fractional):

price = 125
dc = 1.3

discounted_price = discount(price, dc)

print(discounted_price)

Output:

Traceback (most recent call last):
  File "example.py", line 10, in <module>
    discounted_price = discount(price, dc)
  File "example.py", line 3, in discount
    assert 0 <= new_price <= price
AssertionError: Price is less than 0.

As you see, applying an invalid discount crashes the program with an AssertionError. With the help of this assertion error and the traceback, it is easy to track down what went wrong in our code.

AssertionError: Price is less than 0.

In this case, it is the new price that dropped below zero, which means the discount was too high. This is how the assert statement can help you debug your code.

Assert Statement vs If Statement in Python

It may seem like the assert statement and the if statement does the same thing. They both check if a condition is True or False.

But there are key differences between assert and if statements in Python:

  • An if statement is a part of the logic of the code. The assert statement is used to validate input when debugging code.
  • If the if statement’s condition is False, the code continues from where we want it to. When an assert statement is False, an error is thrown and the code execution stops completely.
  • An if statement is always there. The assert statements can be disabled and not considered by the Python interpreter. This makes faulty code run.

Assert Multiple Conditions

The point of assertion is to track down bugs and impossible conditions in your program more easily.

You can make multiple assertions in a single assert statement in Python.

But if you do this, you only make your job harder. This is because you cannot determine which one of the conditions caused the bug.

Anyway, here is an example of multiple assert conditions:

assert 1 + 1 == 2 and 1 + 2 == 5, "Error occurred somewhere"

Output:

AssertionError: Error occurred somewhere

But as you can tell from the output, the error took place somewhere. Thus, you have to inspect the assertion conditions to figure out what went wrong. This is why it doesn’t make sense to use multiple conditions when asserting.

Let’s re-format the above by splitting the assertion into two separate statements:

assert 1 + 2 == 3, "Issue with 1 + 2 == 3"
assert 1 + 2 == 5, "Issue with 1 + 2 == 5"

Output:

AssertionError: Issue with 1 + 2 == 5

Now you can instantly tell that it was the last assertion that failed without having to spend a second thinking about it.

Python Assert Statements on Multiple Lines

Although you should try to keep your assert message short and concise, you might want to know a neat little trick you can do to expand the messages to multiple lines.

  1. Wrap the message around a set of parentheses.
  2. Break the lines as desired.
  3. Wrap each line into a set of single or double quotes.

For instance:

assert 1 + 1 == 3, (
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
    "Donec id magna id lectus gravida finibus. In gravida, mauris "
    "condimentum rhoncus sagittis, mi nisl lacinia tortor, non interdum "
    "nisl diam et lectus. Sed vitae ante vestibulum, volutpat neque non, "
    "vehicula erat. Nullam aliquam risus orci, blandit varius metus pulvinar id."
)

Output:

AssertionError: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id magna id lectus gravida finibus. In gravida, mauris condimentum rhoncus sagittis, mi nisl lacinia tortor, non interdum nisl diam et lectus. Sed vitae ante vestibulum, volutpat neque non, vehicula erat. Nullam aliquam risus orci, blandit varius metus pulvinar id.

Python Assert Statement—Do You Need Parentheses?

Be careful with parentheses and assert. In Python 3, assert is a statement, not a function. This means it does not take parenthesis!

Using assert with parenthesis like this is wrong:

assert(1 + 1 == 3, "An error occurred")

Instead, you should use it without parenthesis like this:

assert 1 + 1 == 3, "An error occurred"

The reason why the parenthesis doesn’t work is that assertion with parenthesis always evaluates True. This is because, in the boolean context, any non-empty tuple evaluates True.

For instance, if you convert a tuple (1, 2) to a boolean, you get True:

bool((1, 2)) # Returns True

Similarly:

bool((1+1 == 3, "An error")) # Also returns True

As a result, if you write the assert statement with parenthesis, you are essentially just saying assert(True).

The only way you can use parenthesis with the assert statement is by wrapping the condition to parenthesis but leaving the message out.

For example:

assert (1 + 1 == 3), "An error occurred"

Output:

AssertionError: An error occurred

This assertion works fine because the assertion is not applied to a tuple. Instead, it is applied to the condition.

Assertions Are Not for Data Validation in Python

The assert statements can be turned off in Python. So do not rely on assert statements for data validation. This can lead to big problems as these checks are omitted.

This is not a mistake by Python developers. Instead, it is an intentional decision. It is really dangerous to use assert as a shorthand way for data validation.

Imagine you’re building a social media app with Python. Somewhere in the code, you want to remove users as an administrator of the app. To do this, you assert that the current user is the administrator that has the privilege to delete users before actually deleting one.

Here is what your code would look like:

def delete_account(user_id, user):
    assert user.is_admin(), "Must be admin to delete"
    users.find_user(user_id).delete()

If you now take a closer look at this function, what do you think happens when the assertions are disabled?

It causes a serious issue. Any user can delete any account given a user ID. This happens because the admin check is now a null operation due to assertions being disabled.

This kind of behavior would be catastrophic for your application.

So do not use assertions to do data validation. You can use a regular if statement instead.

For instance:

def delete_account(user_id, user):
    if not user.is_admin():
        raise AuthError("Must be admin to delete")
    users.find_user(user_id).delete()

This approach is also better as it:

  • Does not pose a security risk
  • Raises an AuthError, instead of a mysterious AssertionError.

How to Disable Assertions in Python

You can disable assertions in Python by executing your program file with the -O flag. This sets the __debug__ to False.

For instance, given a Python program in a file called example.py you can disable the assertions by running the code with:

python -O example.py

Now no assert statements are triggered regardless of whether there was a bug or not.

Conclusion

Today you learned how Python assert statements works.

The assert statement in Python is meant to debug your code—not to handle runtime errors.

An assert statement can be thought of as a sanity check. It helps developers make sure what they think is true really is true.

Thanks for reading. Happy coding!

Further Reading