⚠️ 程序一定会出错,但高手不是“try 一把”,而是设计一个稳定可靠的异常策略系统。
✅ 本文目标
- 异常处理基础语法:
try / except / else / finally
- 多层异常策略设计
- 自定义异常类
- 构建一个稳定型爬虫请求框架
🧩 一、异常的最基础用法
try:
num = int(input("请输入一个整数:"))
print(100 / num)
except ValueError:
print("❌ 输入的不是整数")
except ZeroDivisionError:
print("❌ 不能除以 0")
else:
print("✅ 执行成功")
finally:
print("📌 程序结束")
输出:
🔍 二、把“异常”当做一种设计语言
🧱 错误等级:小错不中断,大错才终止
def parse_age(raw):
try:
return int(raw)
except:
return -1 # 特殊值,表示转换失败
但更推荐显式抛出异常 + 业务兜底处理。
🚨 三、自定义异常:让程序逻辑更清晰
class InvalidAgeError(Exception):
pass
def check_age(age):
if age < 0:
raise InvalidAgeError("年龄不能是负数")
return True
使用:
try:
check_age(-5)
except InvalidAgeError as e:
print(f"❌ 年龄异常:{e}")
输出:
🔁 四、实战:构建一个稳定型爬虫请求工具
目标:自动重试 3 次、打印错误信息、记录日志
import requests
import time
class RequestError(Exception): pass
def safe_get(url, retry=3, delay=1):
for i in range(retry):
try:
resp = requests.get(url, timeout=5)
resp.raise_for_status()
return resp.text
except requests.RequestException as e:
print(f"⚠️ 第{i+1}次请求失败:{e}")
time.sleep(delay)
raise RequestError(f"🚨 请求失败超过 {retry} 次:{url}")
使用:
try:
html = safe_get("https://httpbin.org/status/200")
print("✅ 请求成功")
except RequestError as e:
print(e)
输出:
🛠 五、日志记录 + 异常回传
import logging
logging.basicConfig(filename="error.log", level=logging.ERROR)
try:
1 / 0
except ZeroDivisionError as e:
logging.error("捕获除零错误", exc_info=True)
日志中将记录堆栈信息,非常适合生产系统分析问题。
输出:
🧪 BONUS:异常链 & 多层封装
def fetch_data():
try:
raise ValueError("模拟业务异常")
except Exception as e:
raise RuntimeError("获取数据失败") from e
你可以在日志中看到两层异常:
RuntimeError: 获取数据失败
--> caused by: ValueError: 模拟业务异常
💡 拓展方向
- 异常监控平台(如 Sentry、钉钉通知)
- 异常回传接口 + 报警系统
- 异常 + 日志 + 自动重试组成“稳定链”
🧠 总结一句话
初学者写异常为了“别报错”,高手设计异常是为了“系统永不崩”。