Python 3.10.8中TypedDict类型检查报错的原因与解决方法
问题描述
运行包含TypedDict的类型检查代码时,抛出如下错误:
TypeError: TypedDict does not support instance and class checks
最小可复现示例(MWE)
from typeguard import typechecked import sys from typing import Dict, List, Union if sys.version_info < (3, 11): from typing_extensions import NotRequired, TypedDict else: from typing import NotRequired class Run_config(TypedDict): adaptation: Union[None, Dict] algorithm: Dict # Other attributes... @typechecked def some_function(some_int: int, run_config: Run_config) -> Run_config: """Returns a dict""" print(f'some_int={some_int}') return run_config some_run_config: Run_config = { "adaptation": None, "algorithm": {"hi":2}, # Other items... } some_int: int = 5 some_function(some_int, some_run_config)
堆栈跟踪信息
$python -m src.mwe hello world Traceback (most recent call last): File "/home/name/anaconda/envs/snncompare/lib/python3.10/runpy.py", line 196, in _run_module_as_main return _run_code(code, main_globals, None, File "/home/name/anaconda/envs/snncompare/lib/python3.10/runpy.py", line 86, in _run_code exec(code, run_globals) File "/home/name/git/snn/mwe/src/mwe/__main__.py", line 50, in <module> some_function(some_int,some_run_config) File "/home/name/anaconda/envs/snncompare/lib/python3.10/site-packages/typeguard/__init__.py", line 1032, in wrapper check_argument_types(memo) File "/home/name/anaconda/envs/snncompare/lib/python3.10/site-packages/typeguard/__init__.py", line 875, in check_argument_types raise TypeError(*exc.args) from None TypeError: TypedDict does not support instance and class checks
请问该错误产生的原因是什么,应如何解决?
原因与解决方案
错误原因
问题根源是使用的typeguard版本过低。旧版本的typeguard在处理TypedDict类型时,会尝试通过isinstance()或类检查的方式验证类型,但TypedDict本质是静态类型提示工具,并非实际的Python类,无法支持实例或类层面的检查,因此触发该错误。
解决方案
方案1:升级typeguard到兼容版本
typeguard从2.13.0版本开始正式支持TypedDict的运行时类型检查。执行以下命令升级:
pip install --upgrade typeguard>=2.13.0
升级后原代码无需任何修改即可正常运行,typeguard会自动验证TypedDict的键完整性与对应值的类型。
方案2:手动验证TypedDict结构(不升级依赖时)
如果无法升级typeguard,可以在函数内部手动实现字典结构与类型的校验:
@typechecked def some_function(some_int: int, run_config: dict) -> dict: """Returns a dict""" # 验证必填与允许的键 required_keys = {"algorithm"} allowed_keys = {"adaptation", "algorithm"} if not required_keys.issubset(run_config.keys()): raise TypeError(f"run_config缺少必填键: {required_keys - run_config.keys()}") if not run_config.keys().issubset(allowed_keys): raise TypeError(f"run_config包含非法键: {run_config.keys() - allowed_keys}") # 验证对应值的类型 if not isinstance(run_config["algorithm"], Dict): raise TypeError(f"algorithm必须是Dict类型,实际为{type(run_config['algorithm'])}") if run_config["adaptation"] is not None and not isinstance(run_config["adaptation"], Dict): raise TypeError(f"adaptation必须是None或Dict类型,实际为{type(run_config['adaptation'])}") print(f'some_int={some_int}') return run_config
这种方式需要手动维护键和类型的校验逻辑,适合无法升级依赖的场景。
方案3:改用dataclass替代TypedDict(业务场景允许时)
如果不需要纯字典结构,可以改用dataclasses.dataclass,它支持运行时实例检查:
from dataclasses import dataclass from typeguard import typechecked import sys from typing import Dict, Union @dataclass class Run_config: adaptation: Union[None, Dict] algorithm: Dict # Other attributes... @typechecked def some_function(some_int: int, run_config: Run_config) -> Run_config: """Returns a Run_config instance""" print(f'some_int={some_int}') return run_config some_run_config = Run_config( adaptation=None, algorithm={"hi":2}, # Other items... ) some_int: int = 5 some_function(some_int, some_run_config)
注意这种方式传入的是类实例而非字典,需根据业务场景判断是否适用。
内容的提问来源于stack exchange,提问作者a.t.
相关产品推荐
相关产品推荐

