python学习-程序异常处理
本文介绍 python 如何进行程序异常处理,以及程序异常处理的各种细节:常见的异常处理、设计多组异常处理程序、丢出异常、
finally
语句、程序断言assert
和日志logging
模块。供自己以后查漏补缺,也欢迎同道朋友交流学习。
引言
之前的几篇文章都写的是程序怎么写的正确,但很多时候,程序运行时会报错,这时候我们就需要对程序进行异常处理,让程序可以正常运行。
所以,本篇文章主要介绍如何进行 python
的程序异常处理,以及程序异常处理的各种细节:常见的异常处理、设计多组异常处理程序、丢出异常、finally
语句、程序断言 assert
和日志 logging
模块。
程序异常
异常处理
在编程中,异常是指程序在运行时发生的错误,这些错误可能是由于代码中存在的逻辑错误
、外部环境的变化(如文件不存在
、网络连接失败
等),或者是用户的非法操作
引起的。
在 Python
中,异常是 Exception
类或者其子类的实例。当程序执行到可能会发生错误的代码时,如果发生了异常,程序会停止执行并抛出一个异常对象。
异常处理
是程序设计中的一个重要部分,它允许程序在遇到错误时不会立即崩溃
,而是能够以一种控制的方式响应这些错误。
异常处理机制
Python
提供了一套完整的异常处理机制,使得程序员可以捕获和处理异常,防止程序因未处理的错误而中断执行。
- try关键字 :
try
块是异常处理的核心,它允许程序员测试可能引发异常的代码。如果try
块中的代码执行成功,那么except
块将被跳过;如果发生异常,则跳转到except
块执行。 - except关键字 :
except
块用于捕获并处理特定类型的异常。可以有多个except
块,分别处理不同类型的异常。 - else关键字 :
else
块是可选的,仅当try
块没有发生任何异常时执行。 - finally关键字 :
finally
块也是可选的,无论是否发生异常,它都会被执行。这通常用于执行清理操作,如关闭文件
或释放资源
。
python
try:
# 尝试执行的代码
result = 10 / 0
except ZeroDivisionError:
# 处理除以零的异常
print("除以零错误")
except Exception as e:
# 处理其他类型的异常
print(f"发生了异常:{e}")
else:
# 如果没有异常发生,执行这里的代码
print("一切正常")
finally:
# 无论是否发生异常,都会执行这里的代码
print("清理资源")
常见的异常类型
在程序中有太多不可预期的异常发生了,所以我们需要对这些异常进行处理,让程序可以正常运行。我们有必要简单了解下有哪些常见的异常类型:
异常对象名称 | 说明 |
---|---|
AttributeError | 访问对象属性时发生错误 |
Exception | 通用异常类 |
FileNotFoundError | 文件未找到错误 |
IOError | 输入/输出错误 |
IndexError | 索引超出范围错误 |
KeyError | 字典中不存在的键错误 |
NameError | 未定义名称错误 |
SyntaxError | 语法错误 |
TypeError | 类型错误 |
ValueError | 值错误 |
ZeroDivisionError | 除以零错误 |
MemoryError | 内存错误 |
SystemError | 系统错误 |
设计多组异常处理程序
单一异常处理
单一异常处理
是指针对特定类型的异常编写处理代码。这种方式允许程序对不同类型的错误做出不同的响应。
python
value = '2.1'
# 单一异常处理
try:
# 尝试将输入转换为整数
number = int(value)
except ValueError:
# 处理非整数输入的情况
print("错误:您输入的不是一个有效的整数。")
多异常处理
多异常处理
允许程序同时处理多个不同的异常。这可以通过多个 except
子句实现。
python
value2 = '0'
try:
# 尝试将输入转换为整数
number2 = int(value2)
# 尝试将整数除以零
result = 10 / number2
except ValueError:
# 处理非整数输入的情况
print("错误:您输入的不是一个有效的整数。")
except ZeroDivisionError:
# 处理除以零的情况
print("错误:不能除以零。")
异常链
异常链
是指在捕获一个异常的同时,保留原始异常的信息。这可以通过在 except
子句中使用 from
关键字来实现。
python
value3 = '5.5'
try:
# 尝试将输入转换为整数
number3 = int(value)
except ValueError as e:
# 处理非整数输入的情况,并抛出新的异常
raise ValueError("输入错误:请输入一个有效的整数") from e
使用异常链的好处是,它允许在上层函数
中捕获并处理异常
,同时保留原始异常
的堆栈跟踪信息,这对于调试和错误日志记录非常有用。
丢出异常
手动抛出异常
手动抛出异常
通常用于强制执行某些条件,或者当检测到错误状态时需要立即停止程序的进一步执行。
在 Python
中,可以使用 raise
关键字来手动抛出一个异常。
python
def check_age(age):
if age < 0:
# 手动抛出异常
raise ValueError("年龄不能为负数")
else:
print("年龄检查通过")
try:
check_age(-5)
except ValueError as e:
print(f"捕获到异常:{e}")
自定义异常
自定义异常
允许你创建特定于你应用程序的异常类型,这可以使得错误处理更加清晰和具体。
python
# 自定义异常
class MyException(Exception):
"""自定义异常类"""
pass
def divide(x, y):
if y == 0:
raise MyException("除数不能为零")
else:
return x / y
try:
result = divide(10, 0)
except MyException as e:
print(f"捕获到自定义异常:{e}")
异常的传递
异常的传递
涉及到异常如何在函数调用栈中从被触发的地方传递到被捕获的地方。
如果一个异常在当前函数中没有被捕获,它将被传递到调用栈中的上一个函数,依此类推,直到被捕获或者导致程序终止。
python
def outer_function():
try:
inner_function()
except ValueError as e:
print("在外部函数中捕获异常:", e)
def inner_function():
try:
raise ValueError("这是一个错误")
except ValueError as e:
raise # 重新抛出当前异常,允许外部函数捕获
outer_function()
finally 语句
finally的作用
finally
的主要目的是提供一个清理的环节,确保即使在发生异常时也能执行某些代码。这对于防止资源泄露和其他清理工作至关重要。
python
try:
f = open("file.txt", "r")
data = f.read()
except IOError as e:
print(f"文件操作出错:{e}")
finally:
f.close() # 确保文件被关闭
程序断言 assert
断言(assert
)是一种用于调试的语句,它用于验证程序中的某个条件是否为真。
如果条件为真,则程序继续执行;
如果条件为假,则程序抛出 AssertionError
异常。
断言通常用于检查程序中不应该发生的情况,或者确保函数的输入参数满足预期的条件
基础用法:
python
assert 条件, 错误消息
断言的使用:
python
def calc_discount(price, discount):
assert price > 0, "价格必须大于0"
assert 0 <= discount <= 1, "折扣必须在0到1之间"
return price * (1 - discount)
try:
print(calc_discount(100, -0.2))
except AssertionError as e:
print(f"断言错误: {e}")
日志模块 logging
日志模块概述
logging
模块允许程序生成日志信息,这些信息可以输出到不同的地方,如控制台
、文件
、网络
等。
提供了日志记录的四个主要组成部分:日志记录器(Loggers
)、日志处理器(Handlers
)、日志格式化器(Formatters
)和日志过滤器(Filters
)。
可以通过 logging.basicConfig()
函数快速配置日志系统
,设置日志级别
、日志文件名
、日志格式
等。
日志级别
logging
模块定义了五个日志级别,按严重性从低到高排序如下:
- DEBUG :详细的信息,通常只在
诊断问题
时有用。 - INFO :确认程序按预期运行的
信息
。 - WARNING :指示有
潜在问题
的情况(例如,程序回退到一个更慢的算法)。 - ERROR :由于更严重的问题,程序的某些功能
无法执行
。 - CRITICAL :
严重错误
,表明程序本身可能无法继续运行。
python
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug("这是一条 debug 级别的日志")
logging.info("这是一条 info 级别的日志")
logging.warning("这是一条 warning 级别的日志")
logging.error("这是一条 error 级别的日志")
logging.critical("这是一条 critical 级别的日志")
自定义日志格式和处理器
日志格式:
日志的格式可以通过创建 Formatter
对象来自定义。
python
import logging
format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logging.basicConfig(level=logging.DEBUG, format=format)
logger = logging.getLogger(__name__)
logger.debug('这是一条 debug 级别的日志')
自定义日志处理器:
日志处理器决定了日志信息的输出位置,如控制台、文件等。
python
import logging
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler = logging.FileHandler('app.log')
file_handler.setFormatter(formatter)
logger = logging.getLogger(__name__)
logger.addHandler(file_handler)
logger.setLevel(logging.DEBUG)
logger.info("这条日志将被写入文件")
python学习专栏系列
- python学习-基础学习1
- python学习-基础学习2
- python学习-基础学习3
- python学习-面向对象编程1
- python学习-面向对象编程2
- python学习-文件读写
- python学习-程序异常处理