10_异常处理

Python 异常处理

异常是程序执行过程中发生的错误。Python提供了强大的异常处理机制,让我们能够优雅地处理错误情况,防止程序崩溃。

什么是异常?

当Python检测到错误时,会引发异常。如果没有处理异常,程序将会终止并显示错误信息。

python 复制代码
# 这将引发ZeroDivisionError异常
# print(10 / 0)

# 这将引发ValueError异常
# int("abc")

try...except 语句

基本的异常处理结构是try...except语句:

python 复制代码
try:
    # 可能出现异常的代码
    result = 10 / 0
except:
    # 处理异常的代码
    print("发生了错误")

捕获特定异常

可以捕获特定类型的异常:

python 复制代码
try:
    x = int(input("请输入一个数字: "))
    y = 10 / x
    print(f"结果是: {y}")
except ValueError:
    print("输入的不是有效数字")
except ZeroDivisionError:
    print("不能除以零")

使用as关键字获取异常信息

python 复制代码
try:
    x = int(input("请输入一个数字: "))
    y = 10 / x
except ValueError as e:
    print(f"值错误: {e}")
except ZeroDivisionError as e:
    print(f"除零错误: {e}")

else 子句

else子句在没有异常发生时执行:

python 复制代码
try:
    x = int(input("请输入一个数字: "))
    y = 10 / x
except ValueError:
    print("输入的不是有效数字")
except ZeroDivisionError:
    print("不能除以零")
else:
    print(f"结果是: {y}")

finally 子句

finally子句无论是否发生异常都会执行:

python 复制代码
try:
    file = open("example.txt", "r")
    content = file.read()
    print(content)
except FileNotFoundError:
    print("文件未找到")
finally:
    try:
        file.close()
        print("文件已关闭")
    except:
        print("无法关闭文件")

抛出异常

使用raise语句可以手动抛出异常:

python 复制代码
def check_age(age):
    if age < 0:
        raise ValueError("年龄不能为负数")
    elif age > 150:
        raise ValueError("年龄不能超过150")
    else:
        print(f"年龄 {age} 是有效的")

try:
    check_age(-5)
except ValueError as e:
    print(f"错误: {e}")

自定义异常

可以通过继承Exception类创建自定义异常:

python 复制代码
class CustomError(Exception):
    """自定义异常类"""
    def __init__(self, message):
        self.message = message
        super().__init__(self.message)

class AgeError(Exception):
    """年龄相关异常"""
    pass

def validate_age(age):
    if age < 0:
        raise AgeError("年龄不能为负数")
    elif age > 150:
        raise AgeError("年龄不能超过150")

try:
    validate_age(200)
except AgeError as e:
    print(f"年龄验证错误: {e}")

常见异常示例

python 复制代码
# IndexError - 列表索引超出范围
try:
    my_list = [1, 2, 3]
    print(my_list[5])
except IndexError as e:
    print(f"索引错误: {e}")

# KeyError - 字典键不存在
try:
    my_dict = {"a": 1, "b": 2}
    print(my_dict["c"])
except KeyError as e:
    print(f"键错误: {e}")

# AttributeError - 属性不存在
try:
    my_string = "hello"
    my_string.append("world")
except AttributeError as e:
    print(f"属性错误: {e}")

# TypeError - 类型错误
try:
    result = "5" + 5
except TypeError as e:
    print(f"类型错误: {e}")

# FileNotFoundError - 文件未找到
try:
    with open("nonexistent.txt", "r") as file:
        content = file.read()
except FileNotFoundError as e:
    print(f"文件未找到错误: {e}")

多个异常处理

可以在一个except子句中处理多种异常:

python 复制代码
try:
    x = int(input("请输入一个数字: "))
    result = 10 / x
    my_list = [1, 2, 3]
    print(my_list[x])
except (ValueError, ZeroDivisionError, IndexError) as e:
    print(f"发生了以下错误之一: {type(e).__name__}: {e}")

异常链

可以将一个异常作为另一个异常的原因:

python 复制代码
def process_data(data):
    try:
        return int(data)
    except ValueError as e:
        raise TypeError("数据处理失败") from e

try:
    process_data("abc")
except TypeError as e:
    print(f"类型错误: {e}")
    print(f"原因: {e.__cause__}")

上下文管理器和with语句

许多资源管理场景可以使用with语句自动处理异常:

python 复制代码
# 文件操作中的异常处理
try:
    with open("example.txt", "r") as file:
        content = file.read()
        # 即使发生异常,文件也会自动关闭
        result = 10 / 0  # 这会引发异常
except FileNotFoundError:
    print("文件未找到")
except ZeroDivisionError:
    print("除零错误")
# 文件在此处已经自动关闭

断言

assert语句用于调试,如果条件为假则引发AssertionError:

python 复制代码
def divide(x, y):
    assert y != 0, "除数不能为零"
    return x / y

try:
    result = divide(10, 0)
except AssertionError as e:
    print(f"断言错误: {e}")

日志记录与异常

结合日志记录可以更好地追踪异常:

python 复制代码
import logging

# 配置日志
logging.basicConfig(level=logging.ERROR)

def divide_numbers(x, y):
    try:
        result = x / y
        return result
    except ZeroDivisionError as e:
        logging.error(f"除零错误: {e}")
        return None
    except Exception as e:
        logging.error(f"未知错误: {e}")
        return None

result = divide_numbers(10, 0)

最佳实践

  1. 具体异常优于通用异常:捕获具体的异常类型而不是使用裸露的except
  2. 不要忽略异常:即使不需要处理异常也不要空的except块
  3. 使用finally清理资源:确保重要资源得到释放
  4. 记录异常信息:使用日志记录异常以便调试
  5. 自定义异常要有意义:创建能够清楚表达业务逻辑的异常类
  6. 异常处理不应影响正常流程:异常处理代码应该是辅助性的

实际应用示例

网络请求异常处理

python 复制代码
import urllib.request
import urllib.error

def fetch_url(url):
    try:
        response = urllib.request.urlopen(url)
        return response.read()
    except urllib.error.HTTPError as e:
        print(f"HTTP错误: {e.code} {e.reason}")
    except urllib.error.URLError as e:
        print(f"URL错误: {e.reason}")
    except Exception as e:
        print(f"未知错误: {e}")
    return None

# content = fetch_url("https://www.example.com")

数据库操作异常处理

python 复制代码
# 示例伪代码
def database_operation():
    connection = None
    try:
        # connection = connect_to_database()
        # result = execute_query(connection, "SELECT * FROM users")
        pass
    except ConnectionError as e:
        print(f"数据库连接错误: {e}")
    except SQLSyntaxError as e:
        print(f"SQL语法错误: {e}")
    finally:
        if connection:
            # connection.close()
            pass

结论

异常处理是编写健壮Python程序的关键部分。通过合理使用try、except、else和finally语句,我们可以创建能够优雅处理错误情况的应用程序。良好的异常处理不仅能防止程序崩溃,还能提供有用的错误信息,帮助用户理解问题所在并采取相应措施。

相关推荐
肥猪猪爸2 小时前
TextToSql——Vanna的安装与使用
人工智能·python·算法·机器学习·大模型·ollama·vanna
_UMR_2 小时前
多线程场景的学习3,使用CountDownLatch
java·开发语言
无限大.2 小时前
验证码对抗史
java·开发语言·python
June`2 小时前
C++11(四):特殊类与单例模式设计精要
开发语言·c++
代码不行的搬运工2 小时前
面向RDMA网络的Swift协议
开发语言·网络·swift
明月别枝惊鹊丶2 小时前
【C++】GESP 三级手册
java·开发语言·c++
不如打代码KK2 小时前
Java SPI与Spring Boot SPI的区别
java·开发语言·spring boot
代码or搬砖2 小时前
自定义注解全面详解
java·开发语言
南_山无梅落3 小时前
4-Python3输入输出学习笔记:input()与print()的灵活使用
笔记·python·学习·input·print