”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Python 中的错误处理和日志记录

Python 中的错误处理和日志记录

发布于2024-08-14
浏览:280

Writing software is an activity far from perfect. From ideation to production, errors can appear, and in some cases, failure can occur deliberately. This is why understanding error handling and logging in your primary programming language is a critical skill to master.

Errors can happen, and situations can arise, but how you respond—with preparation and information on the error—will get you out of the situation as quickly as possible.

In this article, we will learn about error handling and logging in Python. We will primarily explore exceptions and how to use Python’s logging package to write various types of logs.

If you are interested in more content covering topics like this, subscribe to my newsletter for regular updates on software programming, architecture, and tech-related insights.

Exceptions in Python

As in many other programming languages, Python has the capability to raise exceptions when errors occur. In programming, an exception is an event that occurs during the execution of a program, disrupting the normal flow of instructions.

In Python, exceptions are errors detected during execution. When an exception occurs, Python stops running the code and looks for a special block of code (a try/except block) to handle the error.

Here are some common exceptions that can occur in a Python program:

  • ZeroDivisionError: Occurs when attempting to divide a number by zero.

  • FileNotFoundError: Occurs when trying to open a file that doesn't exist.

  • ValueError: Occurs when trying to convert a string into an integer when the string does not represent a number.

  • IndexError: Occurs when trying to retrieve an element from a list with a non-existing index.

There are many more exceptions, and Python gives you the ability to create your own exceptions if you need custom behavior. This is a feature we will explore later in the article.

To handle Python exceptions, you need to catch them. Catching exceptions requires a simple syntax known as try/except. Let's explore this.

Try/Except

The try/except block is used to handle exceptions. Code that might raise an exception is placed in the try block, and if an exception occurs, the except block is executed. Here is the syntax of try/except in a code block:

try:
    # Code that might raise an exception
    pass
except ExceptionType as e:
    # Code to handle the exception
    pass

The code that could potentially fail is put inside the try block. If an issue arises, the program’s execution will enter the except block.

Here is a flowchart that illustrates how try/except works:

Error Handling and Logging in Python

Let’s see how we can handle a division by zero with this approach:

# Handling division by zero
try:
    result = 10 / 0
except ZeroDivisionError:
    print("Error: Cannot divide by zero.")
# The code will continue its execution

There are also additional blocks in the try/except syntax, such as else and finally:

try:
    # Code that might raise an exception
    pass
except ExceptionType as e:
    # Code to handle the exception
    pass
else:
    # Code to run if no exception is raised
    pass
finally:
    # Code that always runs, regardless of whether an exception was raised or not
    pass

These blocks are optional but serve specific purposes:

  • else Block (Optional): Contains code that runs if no exceptions are raised in the try block. It is useful for code that should only run when the try block is successful.

  • finally Block (Optional): Contains code that always runs, regardless of whether an exception was raised or not. This is typically used for cleanup actions, such as closing files or releasing resources.

Here is an example where we handle the closing of a file in finally in case of an error:

try:
    # Open the file
    file = open('example.txt', 'r')

    # Read from the file
    content = file.read()

    # Print file content (this will only execute if no exceptions are raised)
    print(content)
except FileNotFoundError as e:
    # Handle the specific exception
    print(f"Error: {e}")
except Exception as e:
    # Handle any other exceptions
    print(f"An unexpected error occurred: {e}")
else:
    # Code that runs if no exception was raised in the try block
    print("File read successfully.")
finally:
    # Ensure the file is closed, regardless of whether an exception was raised
    try:
        file.close()
        print("File closed.")
    except:
        # Handle the case where file was never opened (e.g., if open() failed)
        print("File was not opened or already closed.")

Disclaimer: The example above demonstrates file handling using try/except/finally to ensure the file is properly closed even if an error occurs. However, this approach is not ideal for everyday file operations. In practice, it is recommended to use the with statement for file handling in Python. The with statement automatically manages file opening and closing, ensuring that the file is properly closed after its suite finishes, even if an exception occurs.

This is how the try/except works. Now, there might be some confusion with if/else. When should you use try/except, and when should you use if/else?

What’s the difference between try/except and if/else? Use if/else when you want to check conditions that you can predict and handle before they cause errors, and use try/except to catch and manage exceptions that occur during code execution, particularly for errors you can’t easily anticipate.

In the case below, if/else won’t work properly:

filename = 'non_existent_file.txt'

if filename:  # This only checks if filename is not empty, not if the file exists
    # The following line will raise an exception if the file doesn't exist
    content = open(filename, 'r').read()  # This will crash if the file does not exist
    if content:
        print("File content exists:")
        print(content)
    else:
        print("File is empty.")
else:
    print("Filename is invalid.")

Here is a better solution with try/except:

filename = 'non_existent_file.txt'

try:
    content = open(filename, 'r').read()
    if content:
        print("File content exists:")
        print(content)
    else:
        print("File is empty.")
except FileNotFoundError:
    print("Error: File not found.")

In the solution above, the code attempts to open and read a file, checking if its content exists and printing it if present. If the file does not exist, it catches the FileNotFoundError and prints an error message, preventing the program from crashing.

As mentioned earlier in the article, Python allows for custom exceptions. Let’s learn more about it.

Creating Custom Exceptions in Python

In Python, you can define your own exceptions to handle specific error conditions in a more granular way. Custom exceptions are particularly useful in complex applications, such as fintech, where you may need to enforce business rules or handle specific error cases uniquely.

For example, in a fintech application, you might have a scenario where a wallet’s balance is checked against certain criteria. You may want to raise an exception if a wallet’s balance is not sufficient or does not conform to specific rules. Here’s how you can create and use a custom exception for this purpose:

# Define a custom exception
class WalletBalanceError(Exception):
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

# Function that checks wallet balance
def check_wallet_balance(wallet_balance, required_balance):
    if wallet_balance 



In this example, we define a custom exception WalletBalanceError to handle cases where a wallet’s balance does not meet the required criteria. The check_wallet_balance function raises this exception if the wallet’s balance is insufficient, providing a clear and specific error message.

Custom exceptions in Python help make the code more readable and maintainable by clearly defining specific error conditions and handling them in a structured manner.

Now that we know how to handle errors in Python, it’s time to understand what to do when these errors occur. There are many strategies, but keeping a log of these errors can help identify issues later and correct them. In the next section of this article, we will explore logging.

Logging in Python

Logging helps developers track errors, events, or any runtime information in an application or program. Logging is an important and crucial aspect of software engineering as it has the ability to record everything that goes right or wrong in a post-development application. Logging is one of the most important pillars of monitoring.

Python provides a built-in module that can be used for logging

purposes. To use this module, the first thing to do is to import it.

import logging

Then, configure the logger using the basicConfig method. You need to pass parameters to it, such as the log level, the format of the message, and the output file to save the log.

import logging

# Set up the basic configuration for logging
logging.basicConfig(filename='app.log', level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Log messages of various severity levels
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

In the example above, logs will be written to a file called app.log. The log message format includes the timestamp, logger name, log level, and the actual message.

Python logging has different log levels that indicate the severity of an event or message. These log levels allow you to categorize and filter messages based on their importance. Here’s a breakdown of the common log levels in Python:

Log Levels

  1. DEBUG: Detailed information, typically of interest only when diagnosing problems. Used for debugging purposes during development.

  2. INFO: Confirmation that things are working as expected. This is the level you would use for normal operations and informational messages.

  3. WARNING: An indication that something unexpected happened, or indicative of some problem in the near future (e.g., "disk space low"). The software is still working as expected.

  4. ERROR: Due to a more serious problem, the software has not been able to perform some function. An error indicates a significant issue that needs attention.

  5. CRITICAL: A very serious error, indicating that the program itself may be unable to continue running. Critical errors often represent severe problems that require immediate action.

The logging module allows you to control which messages are recorded by setting the logging level. Only messages that are equal to or more severe than the set level will be logged. The default level is WARNING, meaning only WARNING, ERROR, and CRITICAL messages are logged unless you change the logging configuration.

In the code example above, we set the logging level to DEBUG, which means all log messages (DEBUG, INFO, WARNING, ERROR, and CRITICAL) will be recorded in the app.log file.

You can also create custom loggers, which give you more control over how messages are logged. Custom loggers allow you to set up multiple loggers with different configurations, such as different log levels, formats, or output destinations. This is particularly useful in larger applications where you need to separate logs for different modules or components.

Here’s how you can create and use a custom logger:

import logging

# Create a custom logger
logger = logging.getLogger('my_custom_logger')

# Set the log level for the custom logger
logger.setLevel(logging.DEBUG)

# Create a file handler to write logs to a file
file_handler = logging.FileHandler('custom.log')

# Create a console handler to output logs to the console
console_handler = logging.StreamHandler()

# Set log levels for the handlers
file_handler.setLevel(logging.ERROR)
console_handler.setLevel(logging.DEBUG)

# Create a formatter for log messages
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Add the formatter to the handlers
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

# Add the handlers to the logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)

# Log messages using the custom logger
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

In this example, we create a custom logger named my_custom_logger. This logger writes ERROR and more severe messages to a file called custom.log, while DEBUG and more severe messages are output to the console. By customizing the loggers, you can tailor the logging behavior to fit the specific needs of your application.

Real-world Example: Logging in a Web Application

In a web application, logging plays a critical role in monitoring and maintaining the system’s health. For example, in a Flask web application, you might use logging to track incoming requests, errors, and performance metrics.

Here’s a basic example of how you can use logging in a Flask application:

from flask import Flask, request
import logging

app = Flask(__name__)

# Set up the basic configuration for logging
logging.basicConfig(filename='webapp.log', level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

@app.route('/')
def index():
    app.logger.info('Index page accessed')
    return 'Welcome to the Flask Web Application!'

@app.route('/error')
def error():
    app.logger.error('Error page accessed')
    raise ValueError('This is a simulated error')

if __name__ == '__main__':
    app.run(debug=True)

In this Flask application, we configure logging to write logs to a file named webapp.log. Each time the index page is accessed, an informational log message is recorded. If the error page is accessed, an error log message is recorded, and a simulated error is raised.

By implementing logging in your web application, you can gain insights into user activity, system errors, and performance issues. This information is invaluable for debugging, troubleshooting, and optimizing the application.

Conclusion

Error handling and logging are essential aspects of software development, ensuring that applications run smoothly and that any issues are quickly identified and resolved.

In this article, we explored exceptions in Python, including how to handle them using try/except, and the importance of logging for tracking errors and events. We also discussed how to create custom exceptions and custom loggers to suit specific application needs.

By mastering error handling and logging, you’ll be better equipped to build robust and maintainable software that can gracefully handle unexpected situations and provide valuable insights into its operation.

If you enjoyed this article, consider subscribing to my newsletter so you don't miss out on future updates.

Your feedback is valuable! If you have any suggestions, critiques, or questions, please leave a comment below.

版本声明 本文转载于:https://dev.to/koladev/error-handling-and-logging-in-python-mi1?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    在chrome 在使用Chrome and IE9中的图像时遇到的一个频繁的问题是围绕图像的持续薄薄边框,尽管指定了图像,尽管指定了;和“边境:无;”在CSS中。要解决此问题,请考虑以下方法: Chrome具有忽略“ border:none; none;”的已知错误,风格。要解决此问题,请使用以下...
    编程 发布于2025-07-13
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-07-13
  • 反射动态实现Go接口用于RPC方法探索
    反射动态实现Go接口用于RPC方法探索
    在GO 使用反射来实现定义RPC式方法的界面。例如,考虑一个接口,例如:键入myService接口{ 登录(用户名,密码字符串)(sessionId int,错误错误) helloworld(sessionid int)(hi String,错误错误) } 替代方案而不是依靠反射...
    编程 发布于2025-07-13
  • PHP阵列键值异常:了解07和08的好奇情况
    PHP阵列键值异常:了解07和08的好奇情况
    PHP数组键值问题,使用07&08 在给定数月的数组中,键值07和08呈现令人困惑的行为时,就会出现一个不寻常的问题。运行print_r($月)返回意外结果:键“ 07”丢失,而键“ 08”分配给了9月的值。此问题源于PHP对领先零的解释。当一个数字带有0(例如07或08)的前缀时,PHP将其...
    编程 发布于2025-07-13
  • Java的Map.Entry和SimpleEntry如何简化键值对管理?
    Java的Map.Entry和SimpleEntry如何简化键值对管理?
    A Comprehensive Collection for Value Pairs: Introducing Java's Map.Entry and SimpleEntryIn Java, when defining a collection where each element com...
    编程 发布于2025-07-13
  • 如何正确使用与PDO参数的查询一样?
    如何正确使用与PDO参数的查询一样?
    在pdo 中使用类似QUERIES在PDO中的Queries时,您可能会遇到类似疑问中描述的问题:此查询也可能不会返回结果,即使$ var1和$ var2包含有效的搜索词。错误在于不正确包含%符号。通过将变量包含在$ params数组中的%符号中,您确保将%字符正确替换到查询中。没有此修改,PDO...
    编程 发布于2025-07-13
  • 表单刷新后如何防止重复提交?
    表单刷新后如何防止重复提交?
    在Web开发中预防重复提交 在表格提交后刷新页面时,遇到重复提交的问题是常见的。要解决这个问题,请考虑以下方法: 想象一下具有这样的代码段,看起来像这样的代码段:)){ //数据库操作... 回声“操作完成”; 死(); } ?> ...
    编程 发布于2025-07-13
  • 如何检查对象是否具有Python中的特定属性?
    如何检查对象是否具有Python中的特定属性?
    方法来确定对象属性存在寻求一种方法来验证对象中特定属性的存在。考虑以下示例,其中尝试访问不确定属性会引起错误: >>> a = someClass() >>> A.property Trackback(最近的最新电话): 文件“ ”,第1行, AttributeError: SomeClass...
    编程 发布于2025-07-13
  • 为什么我的CSS背景图像出现?
    为什么我的CSS背景图像出现?
    故障排除:CSS背景图像未出现 ,您的背景图像尽管遵循教程说明,但您的背景图像仍未加载。图像和样式表位于相同的目录中,但背景仍然是空白的白色帆布。而不是不弃用的,您已经使用了CSS样式: bockent {背景:封闭图像文件名:背景图:url(nickcage.jpg); 如果您的html,css...
    编程 发布于2025-07-13
  • 如何使用“ JSON”软件包解析JSON阵列?
    如何使用“ JSON”软件包解析JSON阵列?
    parsing JSON与JSON软件包 QUALDALS:考虑以下go代码:字符串 } func main(){ datajson:=`[“ 1”,“ 2”,“ 3”]`` arr:= jsontype {} 摘要:= = json.unmarshal([] byte(...
    编程 发布于2025-07-13
  • Python读取CSV文件UnicodeDecodeError终极解决方法
    Python读取CSV文件UnicodeDecodeError终极解决方法
    在试图使用已内置的CSV模块读取Python中时,CSV文件中的Unicode Decode Decode Decode Decode decode Error读取,您可能会遇到错误的错误:无法解码字节 在位置2-3中:截断\ uxxxxxxxx逃脱当CSV文件包含特殊字符或Unicode的路径逃...
    编程 发布于2025-07-13
  • 如何处理PHP文件系统功能中的UTF-8文件名?
    如何处理PHP文件系统功能中的UTF-8文件名?
    在PHP的Filesystem functions中处理UTF-8 FileNames 在使用PHP的MKDIR函数中含有UTF-8字符的文件很多flusf-8字符时,您可能会在Windows Explorer中遇到comploreer grounder grounder grounder gro...
    编程 发布于2025-07-13
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-07-13
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中可能会遇到一个冲突,其中3派对软件包将另一个带有导入套件的path package the Imptioned package the Imptioned package the Imported tocted pac...
    编程 发布于2025-07-13
  • Java数组中元素位置查找技巧
    Java数组中元素位置查找技巧
    在Java数组中检索元素的位置 利用Java的反射API将数组转换为列表中,允许您使用indexof方法。 (primitives)(链接到Mishax的解决方案) 用于排序阵列的数组此方法此方法返回元素的索引,如果发现了元素的索引,或一个负值,指示应放置元素的插入点。
    编程 发布于2025-07-13

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3