Debugging with Assertion in Python
What is Debugging?
While working with computer programs, there is often a chance of displaying unusual behavior by the program or application. This unexpected behavior can be due to a logical or conceptual error occurring in the program. Therefore, there is an immense need to rectify the problem to provide the user with an optimal solution. For this purpose, the developers use a process known as debugging that allows them to identify and correct the possible error causing the anomaly to occur. In simple words, debugging is pinning down and removing bugs from a program, software, or system. There are several debugging methods and tools available for bug detection and correcting errors.
Debugging in Python
Python provides a built-in debugger, namely PDB, for the bugs’ identification. This debugger helps execute a code either in the form of a set of instructions or executing the code line by line. There is also the feature of stopping code execution at any desired line, printing variables, and continuing execution till catching the bug. This debugging method also provides the extension of using ipdb to utilize features from IPython.
Debugging with Assertion
There is a famous method of debugging in Python using assertion statements. This method refers to declaring a specific condition, which the developer is sure of, in the program. Assertion statements in Python resemble the Boolean expressions, which either could be true or false. Once the assertion statement provides a fact about a variable, the program checks whether it is true or not. If the assert condition is true, the execution moves to the next line of code without doing anything. On the other hand, if the condition turns out to be false, it displays an error and stops the execution. Therefore, it quickly identifies the piece of code as having a bug.
Assertion Example in Python
Python uses the ‘assert’ keyword to declare assertion statements. This statement declares that the condition with the asset keyword should always be true. If there is an exception to this rule in the program, the program shows an error. Following is a simple example of using assertion in Python:
number = int ( input ( ‘Please provide a number’ ) ) assert number > = 0 print ('The number is', number )
In the above piece of code, the assert statement ensures that the user must enter a positive number. If the user enters a positive integer, the program executes the print statement displaying the entered number. However, if the user enters a negative number, the program stops the execution and throws an Assertion Error, resultantly displaying the assertion statement along with the line number. Therefore, the debugging method becomes more convenient using the above-discussed method.
Assert with optional messages
The users can also use “assert” with multiple conditional statements such as if and else. Following is the sample code for such a scenario
If a == b: //do something elif a >b: //do something else: assert False, ("Invalid Condition")
In this case, the “if” and “else” statements check for the defined conditions to be true. Additionally, if one of the conditions is valid, it does whatever the developer has mentioned inside the scope of that specific condition. However, if both statements are false, it throws an assertion error with an optional message “Invalid Condition.” This additional message provides the error context and helps the developers identify the error more quickly. Overall, Python’s assert statements are potent tools to write a manageable code and debug it easily.
Common Pitfalls with Using Asserts in Python
When utilizing assertions in Python, there are two crucial considerations.
The first is about bringing security risks and vulnerabilities into your apps, while the second is about a syntax quirk that allows you to write worthless assertions quickly.
Caveat #1 – Don't Use Asserts for Data Validation
In the Python interpreter, assertions can be disabled worldwide. So don’t rely on assert expressions to do data validation or processing.
The main disadvantage of utilizing asserts in Python is that they may be disabled worldwide using the -O and -OO command-line switches and the PYTHONOPTIMIZE environment variable in CPython.
It converts any assert statement into a null operation: the assertions are compiled away and does not evaluate. Therefore none of the conditional expressions are executed.
It is a deliberate design choice shared by many other programming languages. Unfortunately, as a result, using assert statements as a quick and easy way to validate input data becomes exceedingly risky.
Let’s look at a simple example. Assume the user is using Python to create an online store application. There should be a function in your application code that allows you to delete a product at the request of a user:
def delete_product(product_id, user): assert user.is_admin(), 'Must have admin privileges to delete' assert store.product_exists(product_id), 'Unknown product id' store.find_product(product_id).delete()
Because of the inappropriate usage of assert statements, this three-line function example has two severe issues:
- Using an assert statement to check for admin rights is risky.
- When assertions are deactivated, the product exists() check is skipped.
Caveat #2 – Asserts That Never Fail
When a tuple is supplied as the first parameter in an assert statement, the assertion continuously evaluates as true and never fails.
This assertion may never fail.
assert(1 == 2, 'This should fail')
It is since non-empty tuples are always truthy in Python. Thus, when a tuple is passed to an assert statement, the assert condition is always true, rendering the above assert statement pointless because it can never fail and throw an exception.
Because of this unexpected behavior, it is effortless to make incorrect multi-line assertions. It quickly results in broken test cases, giving us a false sense of security in the test code. Assume the user have the following assertion anywhere in the unit test suite:
assert ( counter == 10, 'It should have counted all the items' )
This test case appears to be in perfect condition at first glance. But, on the other hand, this test case would never catch an inaccurate result because it continually evaluates to True, regardless of the status of the counter variable.
Other useful articles:
- OOP in Python
- Python v2 vs Python v3
- Variables, Data Types, and Syntaxes in Python
- Operators, Booleans, and Tuples
- Loops and Statements in Python
- Python Functions and Modules
- Regular Expressions in Python
- Python Interfaces
- JSON Data and Python
- Pip and its Uses in Python
- File Handling in Python
- Searching and Sorting Algorithms in Python
- System Programming (Pipes &Threads etc.)
- Database Programming in Python
- Debugging with Assertion in Python
- Sockets in Python
- InterOp in Python
- Exception Handling in Python
- Environments in Python
- Foundation of Data Science
- Reinforcement Learning
- Python for AI
- Applied Text Mining in Python
- Python Iterations using Libraries
- NumPy vs SciPy
- Python Array Indexing and Slicing
- Python & Libraries