编写软件是一项远非完美的活动。从构思到生产,可能会出现错误,在某些情况下,可能会故意发生失败。这就是为什么理解主要编程语言中的错误处理和日志记录是一项需要掌握的关键技能。
错误可能会发生,情况也可能出现,但是您的应对方式(包括有关错误的准备和信息)将使您尽快摆脱困境。
在本文中,我们将学习 Python 中的错误处理和日志记录。我们将主要探讨异常以及如何使用python的logging包来编写各种类型的日志。
如果您对此类主题的更多内容感兴趣,请订阅我的时事通讯以获取有关软件编程、架构和技术相关见解的定期更新。
python 中的异常
与许多其他编程语言一样,python 能够在发生错误时引发异常。在编程中,异常是在程序执行过程中发生的事件,扰乱了正常的指令流程。
立即学习“Python免费学习笔记(深入)”;
在python中,异常是在执行过程中检测到的错误。当异常发生时,python 会停止运行代码并寻找特殊的代码块(try/ except 块)来处理错误。
以下是 python 程序中可能出现的一些常见异常:
-
zerodivisionerror:尝试将数字除以零时发生。
-
filenotfounderror:尝试打开不存在的文件时发生。
-
valueerror:当字符串不代表数字时尝试将字符串转换为整数时发生。
-
indexerror: 尝试从索引不存在的列表中检索元素时发生。
还有更多的异常,如果您需要自定义行为,python 使您能够创建自己的异常。这是我们将在本文后面探讨的功能。
要处理python异常,你需要捕获它们。捕获异常需要一种称为 try/ except 的简单语法。让我们来探索一下吧。
尝试/除外
try/ except 块用于处理异常。可能引发异常的代码放在try块中,如果发生异常,则执行 except块。以下是代码块中 try/ except 的语法:
1
2
3
4
5
6
|
try :
# code that might raise an exception
pass
except exceptiontype as e:
# code to handle the exception
pass
|
可能失败的代码放在 try 块内。如果出现问题,程序的执行会进入 except 块。
这是一个流程图,说明了 try/ except 的工作原理:
让我们看看如何用这种方法处理被零除的情况:
1
2
3
4
5
6
|
# handling division by zero
try :
result = 10 / 0
except zerodivisionerror:
print ( "error: cannot divide by zero." )
# the code will continue its execution
|
try/ except 语法中还有额外的块,例如 else 和 finally:
1
2
3
4
5
6
7
8
9
10
11
12
|
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
|
这些块是可选的,但有特定目的:
这是一个示例,我们在出现错误时在 finally 中处理文件的关闭:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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." )
|
免责声明: 上面的示例演示了使用 try/ except/finally 进行文件处理,以确保即使发生错误也能正确关闭文件。然而,这种方法对于日常文件操作来说并不理想。在实践中,建议在python中使用with语句进行文件处理。 with 语句自动管理文件的打开和关闭,确保文件在其套件完成后正确关闭,即使发生异常也是如此。
这就是 try/ except 的工作原理。现在,if/else 可能会有些混淆。什么时候应该使用 try/ except,什么时候应该使用 if/else?
try/ except 和 if/else 有什么区别?当您想要检查可以在导致错误之前预测和处理的条件时,请使用 if/else,并使用 try/ except 来捕获和管理代码执行期间发生的异常,特别是对于您无法轻易预见的错误。
在下面的情况下,if/else 将无法正常工作:
1
2
3
4
5
6
7
8
9
10
11
12
|
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." )
|
这里有一个更好的 try/ except 解决方案:
1
2
3
4
5
6
7
8
9
10
11
|
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." )
|
在上面的解决方案中,代码尝试打开并读取文件,检查其内容是否存在,如果存在则打印它。如果文件不存在,它会捕获 filenotfounderror 并打印错误消息,防止程序崩溃。
正如本文前面提到的,python 允许自定义异常。让我们来了解更多吧。
在 python 中创建自定义异常
在python中,您可以定义自己的异常,以更精细的方式处理特定的错误情况。自定义异常在复杂的应用程序中特别有用,例如金融科技,您可能需要强制执行业务规则或以独特的方式处理特定的错误情况。
例如,在金融科技应用程序中,您可能会遇到根据某些条件检查钱包余额的场景。如果钱包余额不足或不符合特定规则,您可能需要提出例外。以下是为此目的创建和使用自定义异常的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
# 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
<p>在这个例子中,我们定义了一个自定义异常 walletbalanceerror 来处理钱包余额不符合要求的情况。如果钱包余额不足,check_wallet_balance 函数会引发此异常,并提供清晰具体的错误消息。</p>
<p>python 中的自定义异常通过明确定义特定的错误条件并以结构化方式处理它们,帮助使代码更具可读性和可维护性。</p>
<p>现在我们知道了如何处理 python 中的错误,是时候了解发生这些错误时该怎么办了。有很多策略,但记录这些错误可以帮助以后发现问题并纠正它们。在本文的下一部分中,我们将探讨日志记录。</p>
<h2>
使用 python 进行日志记录
</h2>
<p>日志记录可帮助开发人员跟踪应用程序或程序中的错误、事件或任何运行时信息。日志记录是软件工程的一个重要且关键的方面,因为它能够记录开发后应用程序中所有正确或错误的情况。日志记录是监控最重要的支柱之一。</p>
<p>python 提供了一个内置模块,可用于日志记录</p>
<p>目的。要使用这个模块,首先要做的就是导入它。<br></p>
<pre class = "brush:php;toolbar:false" >import logging
|
然后,使用 basicconfig 方法配置记录器。您需要向其传递参数,例如日志级别、消息的格式以及保存日志的输出文件。
1
2
3
4
5
6
7
8
9
10
11
12
|
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' )
|
在上面的示例中,日志将写入名为 app.log 的文件中。日志消息格式包括时间戳、记录器名称、日志级别和实际消息。
python 日志记录具有不同的日志级别,指示事件或消息的严重性。这些日志级别允许您根据消息的重要性对其进行分类和过滤。以下是 python 中常见日志级别的细分:
日志级别
-
debug:详细信息,通常仅在诊断问题时才有意义。用于开发过程中的调试目的。
-
info:确认事情按预期进行。这是您用于正常操作和信息性消息的级别。
-
警告:表示发生了意外情况,或表示不久的将来会出现一些问题(例如“磁盘空间不足”)。该软件仍然按预期工作。
-
错误:由于更严重的问题,软件无法执行某些功能。错误表示存在需要注意的重大问题。
-
critical:非常严重的错误,表明程序本身可能无法继续运行。严重错误通常代表需要立即采取行动的严重问题。
日志记录模块允许您通过设置日志记录级别来控制记录哪些消息。仅记录等于或高于设定级别的消息。默认级别是 warning,这意味着除非您更改日志配置,否则只会记录 warning、error 和 critical 消息。
在上面的代码示例中,我们将日志记录级别设置为 debug,这意味着所有日志消息(debug、info、warning、error 和 critical)都将记录在 app.log 文件中。
您还可以创建自定义记录器,这使您可以更好地控制消息的记录方式。自定义记录器允许您设置具有不同配置的多个记录器,例如不同的日志级别、格式或输出目标。这在需要为不同模块或组件分离日志的大型应用程序中特别有用。
以下是创建和使用自定义记录器的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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' )
|
在此示例中,我们创建一个名为 my_custom_logger 的自定义记录器。该记录器将 error 和更严重的消息写入名为 custom.log 的文件,而 debug 和更严重的消息则输出到控制台。通过自定义记录器,您可以定制日志记录行为以满足应用程序的特定需求。
真实示例:登录 Web 应用程序
在 web 应用程序中,日志记录在监控和维护系统健康方面起着至关重要的作用。例如,在 Flask web 应用程序中,您可以使用日志记录来跟踪传入请求、错误和性能指标。
这是如何在 flask 应用程序中使用日志记录的基本示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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)
|
在此 flask 应用程序中,我们配置日志记录以将日志写入名为 webapp.log 的文件。每次访问索引页时,都会记录一条信息日志消息。如果访问错误页面,则会记录错误日志消息,并引发模拟错误。
通过在 web 应用程序中实现日志记录,您可以深入了解用户活动、系统错误和性能问题。此信息对于调试、故障排除和优化应用程序非常宝贵。
结论
错误处理和日志记录是软件开发的重要方面,可确保应用程序顺利运行并快速识别和解决任何问题。
在本文中,我们探讨了 python 中的异常,包括如何使用 try/except 处理异常,以及日志记录对于跟踪错误和事件的重要性。我们还讨论了如何创建自定义异常和自定义记录器以满足特定应用程序的需求。
通过掌握错误处理和日志记录,您将能够更好地构建强大且可维护的软件,可以优雅地处理意外情况并为其操作提供有价值的见解。
如果您喜欢这篇文章,请考虑订阅我的时事通讯,这样您就不会错过未来的更新。
您的反馈很有价值!如果您有任何建议、批评或疑问,请在下面留言。