You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Python函数接收异常类型参数时的MyPy报错

问题描述

我编写了如下Python代码:

from pathlib import Path

def ffind_overview_ex(base_dir: Path, exc: Exception = FileNotFoundError) -> Path:
    try:
        # do something

    except Exception as err:
        raise exc("hello") from err

    ## do some more
    if some_extraordinary_condition:
        raise exc("Wow, it really happened!?")

    return result   # result is of type Path

test = ffind_overview_ex(Path("."), SystemExit)

代码可正常运行,但MyPy抛出了以下类型检查错误:

lib\cnmerge\merger.py:53: error: Incompatible default for argument "exc" (default has type "type[FileNotFoundError]", argument has type "Exception")  [assignment]
lib\cnmerge\merger.py:59: error: "Exception" not callable  [operator]
lib\cnmerge\merger.py:62: error: "Exception" not callable  [operator]
lib\cnmerge\merger.py:67: error: "Exception" not callable  [operator]
test.py:96: error: Argument 2 to "ffind_overview_ex" has incompatible type "type[SystemExit]"; expected "Exception"  [arg-type]
Found 5 errors in 2 files (checked 1 source file)

我的需求是控制ffind_overview_ex()抛出的异常类型,避免编写复杂的异常处理块或兜底异常处理器。已知FileNotFoundError和SystemExit均继承自Exception,请问如何解决MyPy的报错问题?

解决方案

问题核心是参数exc的类型标注错误:你传入的是异常类(比如FileNotFoundError、SystemExit),但标注的类型是Exception(异常实例),MyPy自然会报错。

基础修复方案

直接把exc的类型标注为type[Exception],表示这是一个继承自Exception的类类型:

from pathlib import Path

def ffind_overview_ex(base_dir: Path, exc: type[Exception] = FileNotFoundError) -> Path:
    try:
        # 示例逻辑,替换为你的实际代码
        result = base_dir / "overview.txt"
        if not result.exists():
            raise FileNotFoundError("目标文件不存在")

    except Exception as err:
        raise exc("hello") from err

    # 示例条件,替换为你的实际判断逻辑
    some_extraordinary_condition = False
    if some_extraordinary_condition:
        raise exc("Wow, it really happened!?")

    return result

test = ffind_overview_ex(Path("."), SystemExit)

关键说明

  • type[Exception]明确告知MyPy:参数接受任何继承自Exception的类(而非实例),完全匹配你传入FileNotFoundError、SystemExit的用法
  • 修正后MyPy会识别到exc是可调用的类,能接受字符串参数生成异常实例,解决"not callable"的报错
  • 默认值FileNotFoundError的类型type[FileNotFoundError]是type[Exception]的子类型,符合类型匹配要求

更严格的类型约束(可选)

如果需要限定exc只能是特定的异常子类,可以用TypeVar配合bound参数实现更精准的类型检查:

from pathlib import Path
from typing import TypeVar

# 定义一个绑定到Exception的类型变量
ExcType = TypeVar("ExcType", bound=Exception)

def ffind_overview_ex(base_dir: Path, exc: type[ExcType] = FileNotFoundError) -> Path:
    try:
        # 示例逻辑
        result = base_dir / "overview.txt"
        if not result.exists():
            raise FileNotFoundError("目标文件不存在")

    except Exception as err:
        raise exc("hello") from err

    some_extraordinary_condition = False
    if some_extraordinary_condition:
        raise exc("Wow, it really happened!?")

    return result

test = ffind_overview_ex(Path("."), SystemExit)

这种写法能让MyPy更精准地追踪函数抛出的异常类型,同时保持代码的灵活性。

内容的提问来源于stack exchange,提问作者Rick Manix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 00:19:55