Python零基础入门(六):异常处理
一个null值,让我加班到凌晨两点。
程序没有异常处理,用户输入了非法数据,直接崩溃。日志里只有"NullPointerException",排查了6小时。
从那以后,我写代码第一件事就是处理异常。
一、为什么要处理异常?
先看看没有异常处理会怎样:
# 程序直接崩溃,后面的代码永远不执行result = 10 / 0 # ZeroDivisionErrorprint("这行永远不会执行")
加上try-except,程序就能继续跑:
try: result = 10 / 0except ZeroDivisionError: print("除数不能为零!")print("程序继续运行") # 这行现在能执行了
二、try-except基本语法
最常见的写法,一个try配多个except:
try: num = int(input("输入数字:")) result = 100 / numexcept ValueError: print("不是有效数字!")except ZeroDivisionError: print("不能除以零!")
多个异常合并处理,用元组包起来,代码更简洁:
try: value = int(input("输入数字:")) result = 100 / valueexcept (ValueError, ZeroDivisionError) as e: print(f"出错了:{e}") # e是异常对象,包含错误信息
三、else和finally
else是"没异常才执行",finally是"无论如何都执行":
try: num = int(input("输入数字:")) result = 100 / numexcept ValueError: print("输入无效")except ZeroDivisionError: print("不能除以零")else: print(f"结果:{result}") # 没有异常时执行finally: print("程序结束") # 无论如何都执行,常用于资源清理
finally最常见的用途:资源清理,比如关闭文件、断开数据库连接。
四、主动抛出异常
有时候需要主动告诉调用方"你传的参数有问题":
def set_age(age): if age < 0 or age > 150: raise ValueError(f"年龄必须在0-150之间,当前:{age}") return age# 使用示例try: set_age(200)except ValueError as e: print(f"错误:{e}") # 输出:错误:年龄必须在0-150之间,当前:200
五、自定义异常
Python内置异常不够用?自己造一个:
class InsufficientFundsError(Exception): """余额不足异常""" def __init__(self, balance, amount): self.balance = balance self.amount = amount super().__init__(f"余额不足:需要{amount},当前{balance}")class BankAccount: def __init__(self, balance): self.balance = balance def withdraw(self, amount): if amount > self.balance: raise InsufficientFundsError(self.balance, amount) self.balance -= amount return self.balance# 使用示例account = BankAccount(100)try: account.withdraw(150) # 余额不足会抛出异常except InsufficientFundsError as e: print(f"取款失败:{e}") # 输出:取款失败:余额不足:需要150,当前100
六、异常处理最佳实践
1. 具体异常优于宽泛异常
# 不好:捕获所有异常,连类型错误都不知道try: result = int(user_input)except Exception: print("出错了") # 用户不知道具体是什么错# 好:精确捕获,明确告知用户问题try: result = int(user_input)except ValueError: print("请输入有效的数字") # 用户一看就知道问题在哪
2. 不要忽略异常
# 最糟糕:异常被吞掉了,出了问题完全不知道try: dangerous_operation()except: pass # 这行代码是bug的温床!# 至少记录一下,方便排查import loggingtry: dangerous_operation()except Exception as e: logging.error(f"操作失败:{e}") # 记录日志,问题可追溯
3. EAFP原则
Python推崇"先做再处理",别老想着检查各种边界情况:
# LBYL风格(先检查再操作)——啰嗦if key in dictionary: value = dictionary[key]else: value = default_value# EAFP风格(先操作,出错再处理)——更Pythonictry: value = dictionary[key]except KeyError: value = default_value
下一篇预告:文件操作——让程序读写数据。