Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Disabling Assertions in Production

To learn more about managed attributes, look no further than Managing Attributes With Python’s property().

00:00 Disabling Assertions in Production for Performance. Let’s say you’ve come to the end of your development cycle. Your code has been extensively reviewed and tested. All of your assertions pass, and the 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, but why should you optimize your code in this way?

00:26 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.

00:38 Assertions take time to run, and they consume memory, so it’s advisable to disable them in production, but how can you actually disable them? Well, you have two options.

00:50 Firstly, run Python with the -O or -OO options, and secondly, set the PYTHONOPTIMIZE environment variable to an appropriate value.

01:00 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 __debug__ constant, which is the internal mechanism which Python uses to disable assertions.

01:15 Python has a built-in constant called __debug__. This constant is closely related to the assert statement. Python’s __debug__ is a Boolean constant, which defaults to True.

01:29 It’s a constant because you can’t change its value once the Python interpreter is running.

01:41 Here, you first confirm that __debug__ is a Python built-in that’s always available for you. True is the default value of __debug__, and there’s no way to change its value once the interpreter is running.

02:01 The value of __debug__ depends on which mode Python is running in, normal or optimized. Normal mode is typically used during development, while optimized mode is what you should use in production. Now, what does __debug__ have to do with assertions? In Python, the assert statement is the equivalent to the code seen on-screen.

02:22 If __debug__ is true, then the code under the outer if statement runs. The inner if statement tracks expression for truthiness and raises an AssertionError only if the expression is not true. On the other hand, if __debug__ is false, then the code under the outer if statement doesn’t run, meaning that your assertions will be disabled. In this case, Python is running in optimized mode.

02:47 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.

03:04 You can disable all your assert statements by having the __debug__ constant set to False. To accomplish this task, you can use Python’s -O or -OO command-line options to run the interpreter in optimized mode.

03:18 The -O option internally sets __debug__ to False. This change removes the assert statements and any code that you’ve explicitly introduced under a conditional targeting __debug__.

03:30 The -OO option does the same as -O and also discards docstrings. To see this in action, open your command line or terminal within the directory containing the circle.py file, and run an interactive session with a python -O command or bpython -O, as seen on-screen.

03:52 Once in the interpreter, run the following code.

04:24 Because the -O option disables assertions, the Circle class now accepts a negative radius. As already seen, this behavior is wrong because you can’t have a circle with a negative radius.

04:37 Additionally, the circle’s area is computed using the wrong radius as an input.

04:45 The potential to disable assertions in optimized mode is the main reason why you mustn’t use assert statements to validate input data but as an aid to debugging and testing.

04:55 Note that assertions are typically turned off in production code to avoid any overhead or side effects they may cause. A Pythonic solution for the Circle class would be to turn the .radius attribute into a managed attribute using the @property decorator. This way, you perform the .radius validation every time the attribute changes.

05:27 Now .radius is a managed attribute that provides setter and getter methods using the @property decorator.

05:36 You’ve moved the validation code from .__init__() to the setter method, which is called whenever the class changes the value of .radius.

06:10 For more about managed attributes, check out this Real Python course. Now, the updated Circle class works as expected, even if you run the code in optimized mode.

06:56 You can see that this updated version of Circle validates the value of .radius before assignment, and the class works correctly.

07:03 It raises a ValueError for negative values of .radius. You’ve fixed the bug with an elegant solution.

07:14 An interesting side effect of running Python in optimized mode is that code under an explicit if __debug__ condition is also disabled.

07:26 Consider the script on-screen. The script explicitly checks the value of __debug__ in an ifelse statement. The code in the if block will only run if __debug__ is true.

07:41 If it’s false, then the code in the else block will run. Now, try running the script in normal and optimized mode to check its behavior. When you execute the script in normal mode, the code under the if __debug__ condition runs because __debug__ is true. On the other hand, when you execute the script in optimized mode, __debug__ changes to false, and the code under the else block runs.

08:16 Now you know the basics of using Python’s -O and -OO options to disable your assertions in production code. However, running Python with either of these options every time you need to run your production code seems repetitive and may be error-prone. To automate the process, you can use the PYTHONOPTIMIZE environment variable, and that’s what you’ll be looking at in the next section of the course.

Become a Member to join the conversation.