What happens when your Python code hits an error it did not expect, and the whole programme crashes instead of handling it gracefully? Exception handling is the safety net that lets you catch those errors, decide what to do about them, and keep your programme running, which is exactly what the PCAP-31-03 exam tests you on with the try, except, and finally blocks.
Jump to a section
A simple way to picture Exception Handling: Try, Except, Finally
A commercial kitchen ticket is both a promise and a potential disaster. The head chef reads an order for a steak, medium-rare, with mashed potatoes and a side of asparagus. This ticket is the try block. The chef directs the line cooks to execute each step: sear the steak, mash the potatoes, blanch the asparagus. Everything can go perfectly, and the plate goes to the waiter. But the kitchen knows things go wrong. A steak can be dropped on the floor. The potato masher can break. The asparagus can burn. Each of those failures is a specific exception. The chef has a laminated card taped to the pass: 'Steak dropped: fire a new one immediately.' 'Masher broken: switch to the backup hand masher.' 'Burnt asparagus: use the prepped broccoli from the walk-in.' Those instructions are the except blocks. Each disaster has its own handler. But no matter what happens, at the end of every shift, every single ticket must be filed. The dishwashers clean the pans, the prep cooks restock the station, and the manager locks the walk-in. The chef never skips closing duties, even if a ticket was perfect or the kitchen caught fire. That final ritual is the finally block: the cleanup that runs regardless of success or failure. The ticket is the operation; the disasters are the exceptions; the closing procedure is the guarantee that the kitchen is ready for the next service.
A Python programme executes statements one by one, top to bottom. When it encounters an instruction it cannot complete, it raises an exception. An exception is an event that signals something has gone wrong, like dividing by zero, trying to access a file that does not exist, or asking for an index that is out of range in a list. If the programme does not catch that exception, it terminates immediately and prints a traceback to the console. That is a crash. Exception handling lets you intercept that event and respond to it, rather than letting the programme die.
In Python, you use the try statement to wrap code that might cause an exception. The try block tells Python: 'Watch this code very carefully. If something goes wrong, I have a plan.' After the try block, you write one or more except blocks. An except block contains code that runs only if a specific exception type is raised inside the try block. For example, if you are trying to convert user input to an integer, you can catch a ValueError when the user types letters instead of digits.
The syntax looks like this: - try: - number = int(input("Enter a number: ")) - except ValueError: - print("That was not a valid number.")
If the user enters 'hello', the int() function raises a ValueError. The try block stops executing immediately, and Python jumps to the except ValueError block. The print statement runs, and then the programme continues with the next line after the except block. It does not crash. This is called catching an exception.
You can handle multiple exception types by writing multiple except blocks. Python checks each except block in order and runs the first one whose exception type matches the raised exception. If none match, the exception propagates up and the programme crashes, unless a broader except clause catches it. A bare except block, with no exception type, catches everything. This is dangerous because it can hide bugs, but it exists. The PCAP exam expects you to know this hierarchy.
After all the try and except blocks, you can optionally add a finally block. The finally block always executes, whether an exception was raised or not, and even if a return, break, or continue statement is used inside the try or except blocks. The finally block is the place for cleanup actions that must happen regardless, such as closing a file, releasing a network socket, or releasing a lock. Python guarantees the finally block runs before the try-except block exits, making it a reliable tool for resource management.
A common pattern is try-except-else-finally. The else block runs only if no exception was raised in the try block. It is useful for code that should execute only on success, separate from the code that handles failures. For example: - try: - file = open("data.txt", "r") - except FileNotFoundError: - print("File not found.") - else: - content = file.read() - print(content) - finally: - file.close()
Here, the else block ensures you only read the file if it was successfully opened. The finally block ensures the file is closed, even if the read operation itself raises an exception. This structure replaces older, error-prone patterns where you had to check return codes or use nested if statements to manage resources. Pythonic exception handling is cleaner, more readable, and more reliable than checking return values manually.
Key terms you must know: raise, exception, try, except, else, finally, and traceback. A traceback is the report Python prints when an unhandled exception crashes the programme. It shows the call stack and the line that caused the error. Understanding tracebacks helps you debug, but the PCAP exam tests your ability to prevent them with proper exception handling.
Python has many built-in exception types. The most common ones for PCAP include ZeroDivisionError, ValueError, TypeError, IndexError, KeyError, FileNotFoundError, and AttributeError. You can also define custom exceptions by creating a class that inherits from Exception. The exam expects you to recognise these types and write handlers for them correctly.
Identify the risky code
Look at your programme and find statements that could fail, such as user input conversion, file operations, network calls, or division by zero. These are the candidates to wrap in a try block.
Wrap the risky code in a try block
Place the statements that might raise exceptions inside a try block. Python will watch this block and stop executing it if an exception occurs, then jump to the exception handler.
Write specific except blocks
For each exception type you anticipate, write an except block that handles it appropriately. Name the exception type exactly (e.g., except ValueError:). Order them from most specific to most generic.
Add an optional else block
If you have code that should run only when the try block succeeds without any exception, put it in the else block. This keeps the success path separate from the error handling, making the code clearer.
Add a finally block for cleanup
Place resource release code, like closing files or database connections, in the finally block. This code runs no matter what, ensuring you never leave resources open, even if an exception happens.
Test with deliberately faulty input
Run your code with inputs that trigger each exception type to verify that your handlers work correctly. Confirm that the finally block always prints or executes its cleanup code, even when you force an early exit with return.
An IT professional writes a script to process invoice data from a CSV file uploaded by a business user. The script must read the file, parse each row, and insert the data into a database. Several things can go wrong: the file might be missing, the file might have invalid data, the database might be unreachable, or a row might contain a value that violates a database constraint. Without exception handling, any single failure stops the entire batch job, and the user receives an unhelpful crash message. With exception handling, the script can handle each failure gracefully and report exactly which rows failed and why.
Step by step, the IT professional builds this:
They wrap the file open operation in a try block.
They catch FileNotFoundError to inform the user the file path is wrong.
They catch PermissionError if the script lacks read access.
Inside the file reading loop, they wrap the parsing of each row in another try block.
They catch ValueError for rows where a numeric field contains text, and they log the row number and the bad value to a separate error log file.
They continue to the next row instead of failing the whole script.
When inserting into the database, they catch IntegrityError (a database-specific exception) for duplicate key violations and log a human-readable message.
They use a finally block to close the database connection and the file handle, ensuring no resources leak even if an exception occurs mid-insert.
In a production environment, this pattern is critical. A company processing thousands of invoices daily cannot afford a single bad row to take down the entire pipeline. Exception handling turns an unrecoverable crash into a logged, manageable incident. The IT professional also writes a separate monitoring script that alerts them if the error log grows beyond a threshold, because exceptions that are caught silently can mask bigger problems. This is why the exam focuses on the finally block for cleanup: forgotten open files or database connections are a classic source of production outages.
The IT professional also uses custom exceptions in larger codebases. For example, they define a class called InvalidInvoiceRowError that carries extra data about which field failed. Then they can write an except block that catches only that custom type, prints a detailed message for the user, and logs the full context for debugging. This keeps the code organised and the error handling specific.
The PCAP-31-03 exam tests your ability to write and interpret try-except-finally blocks in multiple choice and code reading questions. Expect questions that present a snippet of code with a try block and ask what the output will be, or whether an exception will be caught. They love to trap you with the following patterns:
The else block executes only if no exception occurs. A common trick question shows an else block that tries to use a variable defined only inside the try block after a successful operation. The variable exists because the try block completed, but candidates sometimes think it does not.
The finally block always executes, even if there is a return statement in the try or except block. This is a classic exam trap. If a function has a try block with a return and a finally block, the finally runs before the function actually returns. The return value is determined, but the finally code still executes. Questions ask what value is returned, and the answer is the value from the return statement, but the finally might print something or modify a mutable object before the function exits.
Multiple except blocks are checked in order. The first match wins. If you put a generic except Exception before a specific except ValueError, the specific block will never run. Exam questions ask which except block catches a given exception type, and the answer depends on the order.
A bare except block traps all exceptions, including KeyboardInterrupt and SystemExit, which are usually undesirable. The exam tests whether you recognise this and understand why it is bad practise.
The raise statement without an argument inside an except block re-raises the same exception. This is called re-raising, and it is used when you want to log the error but let it propagate. The exam asks what happens after a bare raise inside an except handler.
Key definitions to memorise:
Exception: an event that disrupts normal programme flow.
Traceback: the report of the call stack when an exception is not handled.
try: the block that contains code to monitor for exceptions.
except: the block that handles a specific exception type.
else: the block that runs if no exception occurred in the try.
finally: the block that always runs, used for cleanup.
raise: the statement that triggers an exception manually.
Common exam question formats: - 'What is the output of this code?' with a try-except-finally block containing a divide by zero. - 'Which exception is raised by this line?' testing recognition of ValueError, TypeError, etc. - 'Which block always executes?' testing the finally guarantee. - 'What is wrong with this exception handling code?' where the trap is an overly broad except or missing finally.
Study tip: memorise the order of execution: try -> first matching except (if exception) or else (if no exception) -> finally. Practise tracing code on paper without running it, because that is exactly what the exam requires.
The try block contains code that might raise an exception, and execution jumps to the first matching except block when an exception occurs.
The finally block always executes, even if the try or except block contains a return, break, or continue statement.
Multiple except blocks are checked in order, so place specific exception types before generic ones to ensure they are caught.
The else block runs only if no exception was raised in the try block, making it ideal for success-only logic.
A bare except: clause catches all exceptions, including SystemExit and KeyboardInterrupt, which is usually a mistake in production code.
You can re-raise an exception inside an except block using a bare raise statement, which preserves the original traceback.
Custom exceptions are created by subclassing Exception and help organise error handling in large applications.
Python guarantees that the finally block executes before the try-except block exits, making it reliable for releasing resources like files and network connections.
These come up on the exam all the time. Here's how to tell them apart.
else block
Runs only if no exception occurred in the try block.
Ideal for code that depends on successful execution of the try block.
Skipped entirely if an exception is raised and caught.
finally block
Always runs, regardless of whether an exception occurred.
Used for cleanup actions like closing files or releasing resources.
Executes even if there is a return, break, or continue in try or except.
Specific except (e.g., except ValueError)
Catches only one named exception type.
Safer because it does not hide unexpected errors.
Allows different handlers for different error types.
Bare except (except:)
Catches every exception, including SystemExit and KeyboardInterrupt.
Considered bad practise in most production code because it masks bugs.
Should only be used if you re-raise the exception after logging it.
try-except
Separates normal flow from error handling cleanly.
Does not require checking return values or error codes manually.
More readable and reduces nesting in code.
if-else with error checking
Requires explicit checks for every possible failure condition.
Can lead to deeply nested if statements and harder-to-read code.
More error-prone because a missed check can cause a crash.
Raise an exception (raise)
Signals an error condition that can be caught and handled higher up.
Preserves the call stack for debugging.
Does not pollute output with messages meant for the developer.
Print an error message
Only prints a message and continues execution.
Does not allow calling code to react to the error programmatically.
Easily missed in logs or console output, leading to silent failures.
Mistake
The finally block only runs if an exception occurs.
Correct
The finally block always runs, regardless of whether an exception was raised or caught.
Beginners see 'finally' as a response to errors, but it is really a guaranteed cleanup step. Real-life analogies like 'always wash your hands regardless of outcome' help, but many still confuse it with an else block.
Mistake
If you have a return statement in the try block, the finally block will not run.
Correct
The finally block runs even if the try or except block contains a return, break, or continue statement. The function does not return until after the finally completes.
Most languages do not have this guarantee, so programmers coming from other backgrounds assume return is immediate. Python's finally is stricter.
Mistake
Catching Exception with a bare 'except:' is good practise because it prevents all crashes.
Correct
Bare except catches all exceptions including SystemExit and KeyboardInterrupt, which should usually not be caught. It hides bugs and is considered bad practise except in very specific situations like cleanup code that must run regardless.
New developers want to prevent any crash at any cost, and a bare except seems like an easy solution. They do not know that some exceptions are meant to terminate the programme.
Mistake
The except block can access variables that were created in the try block only if the try block succeeded completely.
Correct
If the try block raised an exception partway through, variables defined before the exception point are still accessible in the except block. The try block's scope is the same as the surrounding function.
Beginners think an exception 'undoes' everything in the try block, but only the remaining lines of the try block are skipped. The namespace is unaffected.
Mistake
You can only have one except block per try block.
Correct
You can have multiple except blocks, each handling a different exception type. Python checks them in order and executes the first match.
Beginners are used to simple examples with one except, but real-world code requires handling several distinct error types separately.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
The else block runs only if no exception was raised in the try block. The finally block always runs, whether an exception occurred or not, and is used for cleanup like closing files.
Yes, you can have many except blocks. Python checks them in order and runs the first one whose exception type matches the raised exception. This lets you handle different error types separately.
Yes. The finally block executes before the function actually returns, even if the try or except block contains a return, break, or continue. The return value is determined first, then the finally runs, then the function returns.
If you catch an exception and do not re-raise it or take corrective action, the programme continues silently. This can hide bugs because the error is swallowed. Good practise is to log the error or re-raise it if you cannot handle it fully.
A bare except is an except clause with no exception type, meaning it catches all exceptions. It is bad because it catches KeyboardInterrupt and SystemExit, which are usually meant to terminate the programme. It also makes debugging harder by hiding unexpected errors.
A bare raise inside an except block re-raises the same exception that was caught. It preserves the original traceback, so the exception continues propagating after the handler runs. This is useful for logging errors and then letting the caller handle them.
You've finished Exception Handling: Try, Except, Finally. Continue through the PCAP-31-03 study guide to build a complete picture of the exam.
Done with this chapter?