During the execution of a Python program, various anomalies can prevent the program from running successfully, generate unexpected outputs, or cause abnormal termination. These anomalies are broadly categorized into syntax errors, runtime errors, and logical errors.
Syntax errors , also known as parsing errors , occur when the code violates the grammatical rules of the Python programming language. These errors are detected by the interpreter during the parsing stage, before the actual execution of the program begins.
>>> if marks > 20:
... print "GOOD SCORE"
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("GOOD SCORE")?
Even when a program is syntactically correct, errors can still occur during runtime. These runtime anomalies disrupt the normal flow of execution and are represented in Python as specialized objects called exceptions.
An exception is a Python object that represents an error. When an error occurs during execution (such as division by zero or attempting to open a non-existent file), an exception is said to be "raised". If left unhandled, the program terminates abruptly, printing a traceback to the console.
Python's standard library provides a robust hierarchy of built-in exceptions to handle common runtime errors. The table below outlines the primary built-in exceptions:
| Exception Name | Operational Trigger Condition |
|---|---|
| SyntaxError | Raised when the parser encounters a syntax error in the code. |
| ValueError | Raised when a built-in operation or function receives an argument that has the correct data type but an inappropriate value. |
| IOError | Raised when an I/O operation (such as opening a file) fails due to disk/file system issues. |
| KeyboardInterrupt | Raised when the user interrupts program execution (typically by pressing Delete or Esc/Ctrl+C). |
| ImportError | Raised when the import statement fails to find or load a specified module. |
| EOFError | Raised when the end-of-file condition is reached without reading any data from input(). |
| ZeroDivisionError | Raised when the second argument of a division or modulo operation is zero. |
| IndexError | Raised when a sequence subscript or index is out of its allowable range. |
| NameError | Raised when a local or global variable name is not found or defined. |
| IndentationError | Raised when there is incorrect or inconsistent indentation in the program structure. |
| TypeError | Raised when an operation or function is applied to an object of an inappropriate data type. |
| OverFlowError | Raised when the result of an arithmetic calculation exceeds the maximum limit of the numeric data type. |
Technical Profile: Python Built-in Exception System
Programmers can forcefully trigger exceptions within their code to enforce business logic, validate inputs, or signal exceptional states using explicit control statements.
The raise statement allows programmers to manually throw an exception. Once a raise statement is executed, the normal flow of the program is interrupted, and control jumps to the nearest matching exception handler.
Syntax:
raise exception-name[(optional argument)]
The optional argument is typically a string that provides a descriptive error message to be displayed when the exception is raised.
# Example of raising an exception with a custom message
raise Exception("OOPS!! An Exception has occurred")
The
assert
statement is used to test a boolean expression in a program. If the expression evaluates to
True
, execution continues normally. If it evaluates to
False
, an
AssertionError
is raised.
Syntax:
assert Expression[, arguments]
This statement is commonly used at the beginning of functions to validate input parameters.
def negativecheck(number):
assert(number >= 0), "OOPS... Negative Number"
print(number * number)
To prevent programs from crashing abruptly, programmers write exception handling code to capture runtime errors and execute alternative recovery paths.
When an error occurs, the Python interpreter creates an exception object containing metadata about the error (type, file name, line number). The runtime system then searches for a handler in a reverse hierarchical sequence:
| Core Computer Science Concept | Technical Definition / Operational State | Structural Parameters & Specifications | Computational Function & System Purpose |
|---|---|---|---|
| Throwing an Exception | The creation of an exception object and its transfer to the runtime system. |
Triggered automatically by runtime errors or manually via
raise
/
assert
.
|
Signals that an anomalous state has occurred and halts normal execution flow. |
| Catching an Exception | The execution of a block of code specifically designed to handle a raised exception. |
Defined using
except
blocks associated with a
try
block.
|
Prevents program crashes by executing recovery or logging routines. |
Python provides a structured syntax to isolate suspicious code and handle potential exceptions gracefully using
try
,
except
,
else
, and
finally
blocks.
Suspicious lines of code are placed inside a try block . If an exception occurs within the try block, execution of the block is immediately suspended, and control transfers to the corresponding except block .
try:
numerator = 50
denom = int(input("Enter the denominator: "))
quotient = numerator / denom
print("Division performed successfully")
except ZeroDivisionError:
print("Denominator as ZERO is not allowed")
A single try block can be associated with multiple except blocks to handle different types of exceptions uniquely. Additionally, a default, unnamed except block can be placed at the end to catch any unspecified exceptions.
try:
# Code that may raise multiple exceptions
denom = int(input("Enter denominator: "))
result = 50 / denom
except ZeroDivisionError:
print("Error: Division by zero!")
except ValueError:
print("Error: Invalid integer input!")
except:
print("Error: An unexpected exception occurred!")
The else clause is executed only if no exceptions are raised in the try block. It must be placed after all except clauses.
try:
num = int(input("Enter a number: "))
result = 100 / num
except ZeroDivisionError:
print("Zero division error!")
else:
print("Calculation successful. Result is:", result)
The finally clause is guaranteed to execute regardless of whether an exception was raised or caught. It is commonly used for clean-up actions, such as closing database connections or file streams.
try:
file_obj = open("data.txt", "r")
# Perform file operations
except IOError:
print("File could not be opened")
finally:
print("Executing clean-up. Program complete.")
Consider a program where a try block executes, an unhandled exception (such as ValueError) is raised, and a finally block is defined.
Socio-Technical Analysis & Core Systemic Impact: When an unhandled exception occurs, Python first executes the statements inside the
finallyblock. Once the finally block completes, the unhandled exception is re-raised and propagates up the call stack to the next outer handler or default system handler, ensuring that critical clean-up routines are never bypassed even during fatal application crashes.