如何解决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
相关产品推荐
相关产品推荐

