Python
Exception handling: exploration and best practices of three different methods
Foreword
This article aims to explore three different exception handling methods in
Python
. By having a deep understanding of various exception handling strategies, we can better deal with different programming scenarios and choose the method that best suits our needs.
Exception handling plays a vital role in programming. Proper exception handling can not only improve the robustness of the code, but also enhance the readability and maintainability of the program. In Python
programming, effectively managing exceptions is a key part of improving code quality.
Before we dive in, let’s introduce the topic through a practical programming challenge:
The day before yesterday, a friend asked me a question. When dealing with a loop traversal, since it is difficult to foresee all possible errors, he needs to implement exception handling for each element in the loop to prevent an error in a certain element from affecting the operation of the entire program.
But the result of this is that the code becomes verbose and difficult to maintain due to too many try-except
blocks. In this case, how can we optimize the code to handle exceptions while keeping the code clear and concise?
The sample code is as follows:
for item in html_xpath: try: try: url = item.xpath('//title/url-ellipsis/a/url()') except Exception as e: url = None try: title = item.xpath('//title/text-ellipsis/a/text()') except Exception as e: title=None ... except Exception as e: ...
In this article, we will explore three different methods of exception handling and return to the problem at the end to provide an optimized solution.
Knowledge points
Check out these two articles, it will be more helpful for you to consume this article! !
-
An in-depth introduction to Python exception handling – Python exceptions you don’t know
-
A long article of 10,000 words – Basic configuration of Python logger logging encyclopedia
Here we first summarize the advantages, disadvantages and application scenarios of the three exception handling methods introduced below:
Method | Advantages | Disadvantages | Application scenarios |
---|---|---|---|
try-except block |
Simple, direct and easy to understand. Specific processing logic can be written for different types of exceptions. |
Frequent use in code will lead to verbose code | Suitable for handling errors that are known to occur. Used for error handling within specific functions or code blocks. |
sys.excepthook |
Catch unhandled exceptions globally. Relatively simple to use. |
Cannot prevent the program from terminating due to exception. Only handle exceptions that are not caught by a try-except block.Not applicable in child threads. |
Suitable for logging uncaught exceptions. Error reporting and logging. |
Decorators | Improving code reusability and clarity. Customizable exception handling logic. |
Using and understanding requires a higher level of Python skill.Applies only to decorated functions. |
Applicable to functions that require unified exception handling logic. Used to reduce code duplication and improve maintainability. |
Summary of exception handling methods
There are many ways to handle exceptions in Python
, each suitable for different situations and needs.
By choosing appropriate exception handling methods, we can better manage and handle exceptions in Python
programs.
Here are three common exception handling methods and their advantages and disadvantages:
1. Use try-except blocks
Advantages: Simple, direct and easy to understand; allows writing specific processing logic for different types of exceptions.
Disadvantages: Frequent reuse in code can lead to verbose code.
Sample code:
try: # Code that may cause exceptions result=1/0 except ZeroDivisionError: # Handle specific types of exceptions print("Cannot divide by zero")
Code explanation:
The code uses a try-except
block to catch a specific type of exception (ZeroDivisionError
) and prints an error message.
The code runs as follows:
2. Use sys.excepthook
sys.excepthook
is a global function in Python
that is called when the script encounters an uncaught exception. By default, when an exception is not caught by any try-except
block, Python
will call sys.excepthook
, printing the exception information and Stack trace.
Advantages: Allows catching unhandled exceptions anywhere in the program; relatively simple to use.
Disadvantages: Does not prevent program termination due to unhandled exceptions; can only be used to handle exceptions not caught by try-except
blocks.
Sample code:
import sys def global_exception_handler(exc_type, exc_value, exc_traceback): print("It’s done! The exception is caught here:", exc_value) sys.excepthook = global_exception_handler # Example: Deliberately creating a divide-by-zero error result=1/0 print('It didn’t run to this point!')
Code explanation:
The code configures sys.excepthook
so that when an uncaught exception occurs, it will call the global_exception_handler
function to handle the exception.
It allows catching unhandled exceptions anywhere in the program, but the program will terminate (gracefully exit) after catching the unhandled exception.
The code runs as follows:
- As you can see, the code does not run to the line
print('It didn’t run to this point!')
~
3. Use decorators
Advantages: Improve code reusability and clarity, and reduce duplicate code; exception handling logic can be customized and applied to specific functions.
Disadvantages: Use and understanding of decorators requires a higher Python
skill level than direct try-except
blocks; only applicable Decorated function.
Sample code:
def catch_exceptions(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: print(f"Exception caught in {<!-- -->func.__name__}: {<!-- -->e}") return None return wrapper @catch_exceptions def risky_function(x, y): return x/y result = risky_function(1, 0) print("Program continues execution")
Code explanation:
The code defines a decorator catch_exceptions
that can be applied to all functions that need to be handled. When the decorated function throws an exception, the decorator catches the exception and prints an error message.
The code runs as follows:
- It can be seen that after catching the exception, the program can still execute normally~
4. More robust code
This code adds stack printing and logging based on
Using decorators
. The role of logging must be clear to everyone.
Regarding the use of logging, you can check my previous article.
import logging import traceback importsys # Configure logger logging.basicConfig( filename='app.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', encoding='utf-8', filemode='w' ) def catch_exceptions(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() #Record exception information to the log logging.error(f"Exception caught in {<!-- -->func.__name__}: {<!-- -->e}") logging.error(f"Exception type: {<!-- -->exc_type}") logging.error(f"Exception value: {<!-- -->exc_value}") log_traceback = ''.join(traceback.format_tb(exc_traceback)) logging.error(f"Exception traceback: {<!-- -->log_traceback}") return None return wrapper @catch_exceptions def risky_function(x, y): return x / y # ZeroDivisionError may be raised here result = risky_function(1, 0) print("Program continues execution")
The code runs as follows:
- As you can see, the information recorded in the log is very clear.
Solve the previous problem
This code solves the previous problem, nice~
In this code, I simulated a piece of html
text, and then specifically used the wrong expression in xpath_expression
.
Since the code is only for demonstration, logging and battle stack will not be added here~~
from lxml import html #Define exception handling decorator def catch_exceptions(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: print(f"Exception caught in {<!-- -->func.__name__}: {<!-- -->e}") return 'empty' return wrapper # Use decorators to parse HTML elements @catch_exceptions def parse_element(sub_element, xpath_expression): return sub_element.xpath(xpath_expression) # Sample HTML element item_html = """ <div> <a href="https://frica.blog.csdn.net/?type=blog">frica Link</a> <span>It’s a side dish</span> ... </div> """ # Define the mapping between HTML elements and XPath html_xpath_map = {<!-- --> 'url': "//a/@href", 'title': "//span/text()", 'other': '//dd/dd/ddd/text()', 'age': 'This is not an xpath_expression' } if __name__ == '__main__': result_map = dict() #Create HTML element object element = html.fromstring(item_html) # Traverse the XPath mapping, parse the elements and store the results in the dictionary for key, value in html_xpath_map.items(): result = parse_element(element, value) result_map[key] = result[0] if result else 'empty' #walrus operator # result_map[key] = x[0] if (x := parse_element(element, value)) else 'empty' #Print parsing results print(result_map)
Code explanation:
The main purpose of this code is to solve the problem of handling exceptions during loop traversal.
Simplify exception handling and make your code clearer and concise by using decorators and Xpath.
Overall, this code for exception handling is already very robust! !
Readers who don’t understand, please go back and read my previous article~~
Code running effect:
Summary
In Python
, different exception handling methods are suitable for different scenarios.
- The
try-except
block is suitable for handling errors that are known to occur, and is suitable for error handling in specific functions or code blocks. sys.excepthook
is suitable for recording uncaught exceptions and is used for error reporting and logging, but it cannot prevent program termination.- Decorators are suitable for functions that need to unify exception handling logic to improve code reusability and clarity.
When choosing an exception handling method, you should consider which method to use based on specific needs and project background, and write exception handling code according to best practices and considerations to ensure the robustness and maintainability of the code.
Afterword
This sharing ends here,
see you~