推理基础设施 · Python3.4 raise 与自定义异常
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}")

✍️ 练习

  1. 定义一个异常类 ModelNotFoundError(Exception),初始化时接受一个 name 参数,把它存成 self.name,并用 super().__init__(f"model not found: {name}")
  2. 写一个函数 load_model(name, available={"qwen2.5-7b", "llama3-8b"}),如果 name 不在 available 里,raise ModelNotFoundError(name)
  3. try/except ModelNotFoundError as e,调用 load_model("gpt-99"),打印 f"missing: {e.name}"

💡 思路提示

点开看提示
  1. class X(Exception): 的意思是“X 是一种 Exception”
  2. __init__ 里记得 super().__init__(...) 把消息传给父类
  3. 捕获后 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:    # 这行永远到不了
    ...