03
异常处理 · 4 / 4
3.4 raise 与自定义异常
💡 推理框架会抛一堆自定义异常(ModelNotFoundError、ContextLengthExceededError...)
3.4 raise 与自定义异常
手动抛异常
raise ValueError("错误信息")
if tokens > max_allowed:
raise ValueError(f"context too long: {tokens} > {max_allowed}")
自定义异常:继承 Exception
class InferenceError(Exception):
pass
class ContextTooLongError(InferenceError):
def __init__(self, tokens, limit):
super().__init__(f"context {tokens} > limit {limit}")
self.tokens = tokens
self.limit = limit
为什么推理服务用自定义异常
调用方可以写:
try:
infer(req)
except ContextTooLongError:
return 400, "请求太长,请截断"
except InferenceError:
return 500, "推理失败,请重试"
比 except ValueError 精确得多。
示范
class InferenceError(Exception):
"""所有推理相关异常的基类"""
class ContextTooLongError(InferenceError):
def __init__(self, tokens, limit):
super().__init__(f"context {tokens} > limit {limit}")
self.tokens = tokens
self.limit = limit
def check_context(tokens, limit=2048):
if tokens > limit:
raise ContextTooLongError(tokens, limit)
try:
check_context(4096)
except InferenceError as e:
print(f"推理异常: {e}")
✍️ 练习
- 定义一个异常类
ModelNotFoundError(Exception),初始化时接受一个name参数,把它存成self.name,并用super().__init__(f"model not found: {name}") - 写一个函数
load_model(name, available={"qwen2.5-7b", "llama3-8b"}),如果 name 不在 available 里,raise ModelNotFoundError(name) - 用
try/except ModelNotFoundError as e,调用load_model("gpt-99"),打印f"missing: {e.name}"
💡 思路提示
点开看提示
class X(Exception):的意思是“X 是一种 Exception”__init__里记得super().__init__(...)把消息传给父类- 捕获后
e.name是你自定义的属性,e是异常对象
✅ 参考解法
写不出来再打开
class ModelNotFoundError(Exception):
def __init__(self, name):
super().__init__(f"model not found: {name}")
self.name = name
def load_model(name, available={"qwen2.5-7b", "llama3-8b"}):
if name not in available:
raise ModelNotFoundError(name)
try:
load_model("gpt-99")
except ModelNotFoundError as e:
print(f"missing: {e.name}")
🔍 进阶思考
except 的顺序很重要:先捕获具体的子异常,再捕获父异常。位置反了,子异常永远抓不到(被父类先抓走)。
try:
...
except InferenceError: # 先抓父
...
except ContextTooLongError: # 这行永远到不了
...