Python’s Show
Assertions are a convenient tool for documenting, debugging, and testing code during development. Once you’ve debugged and tested your code with the help of assertions, then you can turn them off to optimize the code for production. Assertions will help you make your code more efficient, robust, and reliable. In this tutorial, you’ll learn:
To get the most out of this tutorial, you should have previous knowledge of expressions and operators, functions, conditional statements, and exceptions. Having a basic understanding of documenting, debugging, and testing Python code is also a plus. Getting to Know Assertions in PythonPython implements a feature called assertions that’s pretty useful during the development of your applications and projects. You’ll find this feature in several other languages too, such as C and Java, and it comes in handy for documenting, debugging, and testing your code. If you’re looking for a tool to strengthen your debugging and testing process, then assertions are for you. In this section, you’ll learn the basics of assertions, including what they are, what they’re good for, and when you shouldn’t use them in your code. What Are Assertions?In Python, assertions are statements that you can use to set sanity checks during the development process. Assertions allow you to test the correctness of your code by checking if some specific conditions remain true, which can come in handy while you’re debugging code. The assertion condition should always be true unless you have a bug in your program. If the condition turns out to be false, then the assertion raises an exception and terminates the execution of your program. With assertions, you can set checks to make sure that
invariants within your code stay invariant. By doing so, you can check assumptions like preconditions and postconditions. For example, you can test conditions along the lines of This argument is not
What Are Assertions Good For?Assertions are mainly for debugging. They’ll help you ensure that you don’t introduce new bugs while adding features and fixing other bugs in your code. However, they can have other interesting use cases within your development process. These use cases include documenting and testing your code. The primary role of assertions is to trigger the alarms when a bug appears in a program. In this context, assertions mean Make sure that this condition remains true. Otherwise, throw an error. In practice, you can use assertions to check preconditions and postconditions in your programs at development time. For example, programmers often place assertions at the beginning of functions to check if the input is valid (preconditions). Programmers also place assertions before functions’ return values to check if the output is valid (postconditions). Assertions make it clear that you want to check if a given condition is and remains true. In Python, they can also include an optional message to unambiguously describe the error or problem at hand. That’s why they’re also an efficient tool for documenting code. In this context, their main advantage is their ability to take concrete action instead of being passive, as comments and docstrings are. Finally, assertions are also ideal for writing test cases in your code. You can write concise and to-the-point test cases because assertions provide a quick way to check if a given condition is met or not, which defines if the test passes or not. You’ll learn more about these common use cases of assertions later in this tutorial. Now you’ll learn the basics of when you shouldn’t use assertions. When Not to Use Assertions?In general, you shouldn’t use
assertions for data processing or data validation, because you can disable assertions in your production code, which ends up removing all your assertion-based processing and validation code. Using assertions for data processing and validation is a common pitfall, as you’ll learn in Understanding Common Pitfalls of Additionally, assertions aren’t an error-handling tool. The ultimate purpose of assertions isn’t to handle errors in production but to notify you during development so that you can fix them. In this regard, you shouldn’t write code that catches assertion errors using a regular Understanding Python’s assert StatementsNow you know what assertions are, what they’re good for, and when you shouldn’t use them in your code. It’s time to learn the basics of writing your own assertions. First, note that Python implements assertions as a statement with the In this section, you’ll learn the basics of using the The Syntax of the assert StatementAn In Python,
Here, Here’s how this statement works in practice: >>>
With a truthy expression, the assertion succeeds, and
nothing happens. In that case, your program continues its normal execution. In contrast, a falsy expression makes the assertion fail, raising an To make your >>>
The message in this assertion clearly states which condition should be true and what is making that
condition fail. Note that the So, whenever you use An important point regarding the For example, an assertion like the following will raise a >>>
This warning has to do with non-empty tuples always being truthy in Python. In this example, the parentheses turn the assertion expression and message into a two-item tuple, which always evaluates to true. Fortunately, recent versions of Python throw a This issue often appears when you’re using long expressions or messages that take more than a single line. In these cases, the parentheses are the natural way to format the code, and you may end up with something like the following:
Using a pair of parentheses to split a long line into multiple lines is a common formatting practice in Python code. However, in the context of an In practice, if you want to
split a long assertion into several lines, then you can use the backslash character (
The backslash at the end of first line of this assertion joins the assertion’s two physical lines into a single logical line. This way, you can have appropriate line length without the risk of a warning or a logical error in your code. There’s an edge case of this parentheses-related issue. If you provide only the assertion expression in parentheses, then >>>
Why is this happening? To create a single-item tuple, you need to place a comma after the item itself. In the code above, the parentheses by themselves don’t create a tuple. That’s why the interpreter ignores the parentheses, and Even though the parentheses seem to work in the scenario described in the above example, it’s not a recommended practice. You can end up shooting yourself in the foot. The AssertionError ExceptionIf the condition of an Most of the time, you won’t raise Finally, That’s it! Now you know the basics of the Exploring Common Assertion FormatsWhen it comes to writing the The following examples showcase a few of these common assertion formats, starting with assertions that compare objects: >>>
Comparison assertions are intended to test conditions that compare two or more objects using comparison operators. These assertions can also include compound expressions based on Boolean operators. Another common assertion format is related to membership tests: >>>
Membership assertions allow you to check if a given item is present in a specific collection, such as a
list, tuple, set, dictionary, or the like. These assertions use the membership operators, The assertion format in the example below is related to an object’s identity: >>>
Identity assertions provide a way to test for an object’s identity. In this case, the assertion expression uses the identity operators,
Finally, you’ll learn how to check the data type of your objects in the context of an assertion: >>>
Type check assertions commonly involve using the built-in
Even though these are some of the most common assertion formats that you’ll find in Python code, there are many other possibilities. For example, you can use the built-in >>>
The Your imagination is the only limit for writing useful assertions. You can write assertions using predicate or Boolean-valued functions, regular Python objects, comparison expressions, Boolean expressions, or general Python expressions. Your assertion will depend on what specific condition you need to check at a given moment. Now you know some of the most common assertion formats that you can use in your code. It’s time to learn about specific use cases of assertions. In the following section, you’ll learn how to use assertions to document, debug, and test your code. Documenting Your Code With AssertionsThe To understand why assertions can be a handy documenting tool, say that you have a function that takes a server name and a tuple of port numbers. The function will iterate over the port numbers trying to connect to the target server. For your function to work correctly, the tuple of ports shouldn’t be empty:
If someone accidentally calls
The advantage of an So, using assertions in situations like the one described above is an effective and powerful way to document your intentions and avoid hard-to-find bugs due to accidental errors or malicious actors. Debugging Your Code With AssertionsAt its core, the In this section, you’ll learn how to use the An Example of Debugging With AssertionsYou’ll typically use assertions to debug your code during development. The idea is to make sure that specific conditions are and remain true. If an asserted condition becomes false, then you immediately know that you have a bug. As an example, say that you have the following
The class’s initializer, The
This method takes a correction coefficient and applies it to the current value of >>>
The first call to In this example, your A Few Considerations on Debugging With AssertionsDevelopers often use In general, the conditions that you check with an If one of these conditions fails, then the program
will crash with an To properly use assertions as a debugging tool, you shouldn’t use A proper use of assertions is to inform developers about unrecoverable errors in a program. Assertions shouldn’t signal an expected error, like a The goal of assertion should be to uncover programmers’ errors rather than users’ errors. Assertions are useful during the development process, not during production. By the time you release your code, it should be (mostly) free of bugs and shouldn’t require the assertions to work correctly. Finally, once your code is ready for production, you don’t have to explicitly remove assertions. You can just disable them, as you’ll learn in the following section. Disabling Assertions in Production for PerformanceNow say that you’ve come to the end of your development cycle. Your code has been extensively reviewed and tested. All your assertions pass, and your code is ready for a new release. At this point, you can optimize the code for production by disabling the assertions that you added during development. Why should you optimize your code this way? Assertions are great during development, but in production, they can affect the code’s performance. For example, a codebase with many assertions running all the time can be slower than the same code without assertions. Assertions take time to run, and they consume memory, so it’s advisable to disable them in production. Now, how can you actually disable your assertions? Well, you have two options:
In this section, you’ll learn how to disable your assertions by using these two techniques. Before doing this, you’ll get to know the built-in Understanding the __debug__ Built-in ConstantPython has a built-in constant called >>>
In this code snippet, you first confirm that The value of
Normal mode is typically the mode that you use during development, while optimized mode is what you should use in production. Now, what does
If On the other hand, if Normal or debug mode allows you to have assertions in place as you develop and test the code. Once your current development cycle is complete, then you can switch to optimized mode and disable the assertions to get your code ready for production. To activate optimized mode and disable your assertions, you can either start up the Python interpreter with the Running Python With the -O or -OO OptionsYou can disable
all your The Running Python
with the Now, what effect does this optimization have on your assertions? It disables them. For an example, open your command line or terminal within the directory containing the >>>
Because the The potential to disable assertions in optimized mode is the main reason why you must not use A Pythonic solution for the
Now Now, the updated >>>
An interesting side effect of running Python in optimized mode is that code under an explicit
This script explicitly checks the value of Now try running the script in normal and optimized mode to check its behavior in each mode:
When you execute the script in normal mode, the code under the Python’s Because both options set Now you know the basics of using Python’s Setting the PYTHONOPTIMIZE Environment VariableYou can also run Python in optimized mode with disabled assertions by setting the To try
Once you’ve set Now go ahead and run the following code from the directory containing your >>>
Again, your assertions are off, and the Another possibility is to set
You can use any integer number to set Running Python in Optimized ModeWhen you run Python, the interpreter compiles any imported module to
bytecode on the fly. The compiled bytecode will live in a directory called Inside For example, when you import code from
The name of each file in this table includes the original module’s name ( The main results of running Python in the first
level of optimization is that the interpreter sets The second level of optimization does the same as the first level. It also removes all the docstrings from the compiled code, which results in an even smaller compiled bytecode. Testing Your Code With AssertionsTesting is another field in the development process where assertions are useful. Testing boils down to comparing an observed value with an expected one to check if they’re equal or not. This kind of check perfectly fits into assertions. Assertions must check for conditions that should typically be true, unless you have a bug in your code. This idea is another important concept behind testing. The Here are a few examples of writing test cases using
All these test cases use the Now, why does
These
advantages make working with For example, the standard-library You can use
The first highlighted line in this output tells you that A remarkable feature to note is that Those lines clearly uncover the root cause of the
failure. In this example, Understanding Common Pitfalls of assertEven though assertions are such a great and useful tool, they have some downsides. Like any other tool, assertions can be misused. You’ve learned that you should use assertions mainly for debugging and testing code during development. In contrast, you shouldn’t rely on assertions to provide functionality in production code, which is one of the main drivers of pitfalls with assertions. In particular, you may run into pitfalls if you use assertions for:
Another common source of issues with assertions is that keeping them enabled in production can negatively impact your code’s performance. Finally, Python has assertions enabled by default, which can confuse developers coming from other languages. In the following sections, you’ll learn about all these possible pitfalls of assertions. You’ll also learn how to avoid them in your own Python code. Using assert for Data Processing and ValidationYou shouldn’t use For example, suppose you’re building an online store with Python, and you need to add functionality to accept discount coupons. You end up writing the following function:
Notice the Now consider the example of a pair of shoes at twenty-five percent off: >>>
All right, >>>
Applying an invalid discount raises an The real problem with the example
above comes if the end user can make direct calls to In general, you can write Here’s a new version of
In this new implementation of Now you can wrap up any calls to this function in a The moral of this example is that you shouldn’t rely on the Handling Errors With assertAnother important pitfall with assertions is that sometimes developers use them as a quick form of error handling. As a result, if the production code removes assertions, then important error checks are also removed from the code. So, keep in mind that assertions aren’t a replacement for good error handling. Here’s an example of using assertions for error handling:
If you execute this code in production with disabled assertions, then What can you do to fix this example? Try updating
Now Don’t ever catch Use assertions only to check errors that shouldn’t happen during the normal execution of your programs unless you have a bug. Remember that assertions can be disabled. Running assert on Expressions With Side EffectsAnother subtle pitfall with the In those situations, the side effect takes place every time your code runs the assertion, which might silently change your program’s global state and behavior. Consider the following toy example, in which a function modifies the value of a global variable as a side effect: >>>
In this example, Using assertions to make sure that your function is returning the correct
item can seem appropriate. However, this will cause the function’s internal side effect to run in every assertion, modifying the original content of To prevent unexpected behaviors like the one in the above example, use assertion expressions that don’t cause side effects. For example, you can use pure functions that just take input arguments and return the corresponding output without modifying the state of objects from other scopes and namespaces. Impacting Performance With assertToo many assertions in production can impact your code’s performance. This issue becomes critical when the asserted conditions involve too much logic, such as long compound conditions, long-running predicate functions, and classes implying a costly instantiation process. Assertions can impact your code’s performance in two main ways. They will:
An To avoid performance issues in production code, you should use Python’s Additionally, to prevent performance issues during development, your assertions should be fairly slim and to the point. Having assert Statements Enabled by DefaultIn Python, assertions are enabled by default. When the
interpreter runs in normal mode, the If you want to disable your assertions, then you need to do it explicitly. You can either run the Python interpreter with the In contrast, other programming languages have assertions disabled by default. For example, if you’re coming into Python from Java, you may assume that your assertions won’t run unless you explicitly turn them on. This assumption can be a common source of confusion for Python beginners, so keep it in mind. ConclusionNow you know how to use Python’s The In this tutorial, you learned:
With this knowledge on the |