1 概述
1.1 背景介绍
Python作为一门广泛应用于编程领域的高级编程语言,以其简洁、易读的语法而闻名。然而,在编写Python程序时,难免会遇到各种各样的错误和异常。为了编写健壮的程序并提高代码的可维护性,了解和正确处理这些错误和异常至关重要。
通过本案例可以帮助我们了解 Python 中错误和异常的产生及处理,了解 Python 中程序遇到异常的处理过程。
1.2 适用对象
- 个人开发者
- 高校学生
1.3 案例时间
本案例总时长预计30分钟。
1.4 案例流程
{{{width="30%" height="auto"}}}
说明:
① 登录华为云,开通开发者空间,进入云主机,打开CodeArts IDE for Python创建工程; ② 编写代码运行。
1.5 资源总览
本案例预计花费总计0元。
| 资源名称 | 规格 | 单价(元) | 时长(分钟) |
|---|---|---|---|
| 开发者空间-云主机 | 2vCPUs | 4GB X86 CodeArts IDE for Python | 免费 | 30 |
2 准备开发环境
2.1 配置云主机并进入
参考“10分钟玩转云主机” 案例介绍中“2.2 申请云主机”章节内容完成华为开发者空间云主机申请与配置,配置云主机建议:“CPU架构”选择“X86”,“操作系统”选择“Ubuntu”。
然后点击“进入桌面”进入云主机。 
2.2 使用CodeArts IDE创建工程
参考“初识云主机:CodeArts IDE入门”案例介绍“3.1 新建工程”章节新建工程。
新建的工程包含如下三个目录文件部分:
| 目录文件 | 说明 |
|---|---|
| .arts | CodeArts的配置文件 |
| venv | 虚拟环境 |
| main.py | 默认生成的入口文件 |

3 异常与程序调试
3.1 Python中的异常
在Python中,异常是指程序中发生的错误或者意外情况,它会导致程序的正常执行流程被中断。Python使用异常处理机制来管理这些错误,使得开发者能够优雅地处理错误情况,而不是让程序因为一个未被捕获的异常而崩溃。
下面练习以帮助我们掌握Python这门编程语言中对于错误处理以及程序调试的相关知识。
3.1.1 代码错误
代码错误通常发生在代码编写时,由于不符合Python的语法规则而导致的错误。例如,遗漏冒号、错误的缩进、拼写错误的关键字等。
代码错误会导致Python解释器无法理解你的代码,因此在尝试运行代码时会立即抛出错误信息,并且通常会指出错误发生的具体位置(例如行号和字符位置)。
代码示例:
# 缩进不规范
def func():
pass
return 0

# 语法错误,没有加“:”
def func()
pass
return 0

3.1.2 异常
异常是在程序运行时发生的错误,它们通常是由于某些运行时条件不满足(例如除以零、使用越界下标、试图访问不存在的文件等)而导致的。
当程序遇到异常时,它不会立即终止,而是会抛出一个异常。如果没有被捕获和处理,程序将终止并显示一个错误消息。但如果异常被妥善处理,程序可以继续执行。
代码示例:
# 除数为 0
def func():
return 1/0
func()

#下标越界
l = [1,2]
def func():
return l[3]
func()

# 文件不存在
with open("file.file") as f:
f.read()

3.2 异常处理
3.2.1 使用try…except语句来捕获异常
try:包含可能引发异常的代码块。如果在try块中发生任何类型的异常,程序将立即跳转到与之匹配的except块进行处理,在可能抛出异常的代码块,使用try语句进行捕获。
代码示例:
# 对于可能为0的除数,使用try语句捕获异常,并打印出错误提示。
def func(num):
return 1/num
try:
num = 0
func(num)
except ZeroDivisionError as e:
print("nun 不能为 0")
3.2.2 直接捕获Exception
Exception:用于捕获并处理 try块中抛出的异常。你可以指定特定类型的异常来捕获,或者不指定任何类型以捕获所有异常。
代码示例:
# 将异常作为参数直接打印出来。
def func(num):
return 1/num
def func2():
l = [1]
return l[1]
try:
num = 1
func(num)
func2()
except Exception as e:
print(e)
3.2.3 finally关键字
finally:无论是否发生异常,finally块中的代码都会被执行。这对于确保资源释放(如关闭文件、网络连接等)非常有用,防止资源泄露。
代码示例:
# finally的代码块无论是否有异常都会执行。
def func2():
l = [1]
return l[1]
try:
func2()
except Exception as e:
print(e)
finally:
print("-----")
3.2.4 自定义异常
在Python中,自定义异常是面向对象编程中的一个重要特性,允许开发者根据程序的具体需求定义新的异常类型。这样做可以提高代码的清晰度和可维护性,使得错误处理更加灵活和具体。
自定义异常通常是通过创建一个新的类来实现的,这个类需要继承自Python的内置异常类Exception或者它的子类。
代码示例:
# 自定义一个基础校验异常。
class UnderAgeError(Exception):
"""当年龄小于18岁时抛出"""
def __init__(self, age, message="年龄未满18岁"):
self.age = age
self.message = message
super().__init__(f"{message}(当前年龄:{age})")
# 验证函数
def validate_age(age):
if age < 18:
raise UnderAgeError(age)
return True
# 测试函数
def register_user(age):
try:
validate_age(age)
print("注册成功!")
except Exception as e:
print(f"注册失败:{e}")
# 测试用例
if __name__ == "__main__":
test_ages = [16, 25]
for age in test_ages:
try:
print(f"\n测试年龄:{age}")
register_user(age)
except Exception as e:
print(f"捕获到意外错误:{e}")
3.3 购物支付系统
结合上面的知识点,来看一个购物支付系统小程序。完整代码参考如下(注意:复制使用请保持缩进相同)。
# 一个保证健壮性的支付系统。
import datetime
import logging
import random
# 配置日志记录
logging.basicConfig(filename='transactions.log', level=logging.INFO)
# 自定义异常体系
class PaymentGatewayError(Exception):
"""支付网关异常基类"""
def __init__(self, code, message, original=None):
super().__init__(message)
self.code = code
self.timestamp = datetime.datetime.now()
self.original = original
class InsufficientFundsError(PaymentGatewayError):
"""余额不足异常"""
def __init__(self, balance, amount):
message = f"余额不足 (当前余额: {balance}, 需要支付: {amount})"
super().__init__(code=1001, message=message)
class NetworkTimeoutError(PaymentGatewayError):
"""网络超时异常"""
def __init__(self, service_name):
message = f"{service_name} 服务响应超时"
super().__init__(code=2001, message=message)
# 业务逻辑类
class ECommerceSystem:
def __init__(self, inventory=10):
self.inventory = inventory
self.connections = []
def validate_order(self, order):
"""订单验证(演示多种验证异常)"""
if not isinstance(order, dict):
raise TypeError("订单必须是字典类型")
required_fields = ['user_id', 'product_id', 'quantity']
for field in required_fields:
if field not in order:
raise KeyError(f"缺少必要字段: {field}")
if order['quantity'] <= 0:
raise ValueError("购买数量必须大于0")
assert isinstance(order['user_id'], int), "用户ID必须是整数"
def process_payment(self, amount):
"""支付处理(演示自定义异常和异常链)"""
try:
# 模拟第三方支付调用
if random.random() < 0.3:
raise ConnectionError("支付网关连接失败")
balance = 100 # 模拟用户余额
if amount > balance:
raise InsufficientFundsError(balance, amount)
return True
except ConnectionError as e:
logging.error("支付网关通信失败")
raise NetworkTimeoutError("支付网关") from e
def handle_order(self, order):
"""订单处理主逻辑"""
try:
print("\n开始处理订单:", order)
# 验证订单
self.validate_order(order)
# 检查库存
if order['quantity'] > self.inventory:
raise InventoryError(self.inventory, order['quantity'])
# 处理支付
amount = order['quantity'] * 100 # 模拟金额计算
payment_result = self.process_payment(amount)
# 扣减库存
self.inventory -= order['quantity']
except (TypeError, ValueError, KeyError, AssertionError) as e:
error_msg = f"订单验证失败: {type(e).__name__} - {str(e)}"
logging.warning(error_msg)
raise ValidationError("订单数据不合法") from e
except InventoryError as e:
logging.error(str(e))
print("库存不足,触发补货流程...")
self.restock(e.required - e.available)
raise
except PaymentGatewayError as e:
logging.error(f"支付失败 [{e.code}]: {e}")
if isinstance(e, NetworkTimeoutError):
print("正在重试支付...")
return self.process_payment(amount)
raise
except Exception as e:
logging.critical(f"未处理的异常: {type(e).__name__} - {str(e)}")
raise ECommerceSystemError("系统错误") from e
else:
logging.info(f"订单处理成功: {order}")
print("发送订单确认邮件...")
return True
finally:
print("释放数据库连接...")
self.connections.clear()
def restock(self, quantity):
"""补货操作(演示finally和资源清理)"""
try:
print(f"正在补货 {quantity} 件...")
if quantity <= 0:
raise ValueError("补货数量必须为正数")
self.inventory += quantity
finally:
print("补货流程结束")
# 辅助异常类
class ValidationError(Exception):
"""验证异常"""
pass
class InventoryError(Exception):
"""库存异常"""
def __init__(self, available, required):
super().__init__(f"库存不足 (当前: {available}, 需要: {required})")
self.available = available
self.required = required
class ECommerceSystemError(Exception):
"""系统级异常"""
pass
# --------------------------
# 测试用例
# --------------------------
if __name__ == "__main__":
system = ECommerceSystem()
test_orders = [
"invalid_order", # 类型错误
{'user_id': "123", 'product_id': 1}, # 字段缺失
{'user_id': 123, 'product_id': 1, 'quantity': -2}, # 数量错误
{'user_id': 123, 'product_id': 1, 'quantity': 20}, # 库存不足
{'user_id': 123, 'product_id': 1, 'quantity': 5}, # 正常订单
]
for idx, order in enumerate(test_orders, 1):
try:
print(f"\n=== 处理订单 {idx} ===")
system.handle_order(order)
except ValidationError as e:
print(f"订单验证失败: {e}")
except InventoryError as e:
print(f"库存错误: {e}")
except PaymentGatewayError as e:
print(f"支付失败 [{e.code}]: {e}")
except ECommerceSystemError as e:
print(f"系统错误: {e}")
else:
print("订单处理成功!")
finally:
print("当前库存:", system.inventory)
print("-" * 40)
同时,可以参考上面代码进行扩展练习,例如:模拟银行卡余额不足,直接切换银行卡支付等。
6万+

被折叠的 条评论
为什么被折叠?



