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

如何解决TextX模型使用Mypy类型检查时的名称未定义错误?

为TextX生成的类型添加Mypy类型检查的解决方案

问题场景

我正在使用Python的TextX模块开发一门语言的原型,该模块可用于解析语法,创建的模型如下:

from textx import metamodel_from_str

funl_grammar = """
    Model: statement *= Statement;

    Statement: FunctionDefinition | Function;

    FunctionDefinition: name=ID '=' function=Function;
    Function: name=ID '(' params*=Param (',' params*=Param)* ')';

    Param: Function | INT | ID | STRING;
    Comment: /#.*$/;
    ID: /[a-zA-Z_][a-zA-Z0-9_]*/;
    INT: /[0-9]+/;
    STRING: /".*"/;
"""

mm = metamodel_from_str(funl_grammar)

当我尝试为函数参数标注TextX生成的Param类型时:

def my_func(param: mm["Param"]):
    ...

收到Mypy错误:error: Name "Param" is not defined [name-defined]。

原因分析

Mypy是静态类型检查器,而mm["Param"]是运行时动态获取的类型,Mypy在静态分析阶段无法识别这个动态生成的类型名称,因此抛出未定义的错误。

解决方案

1. 字符串类型标注(快速临时方案)

将类型标注改为字符串形式,Mypy会将其视为前向引用,跳过静态解析:

def my_func(param: "mm['Param']") -> None:
    ...

或者保留原写法并添加类型忽略注释:

def my_func(param: mm["Param"]) -> None:  # type: ignore[name-defined]
    ...

2. 生成静态类型存根文件(推荐长期方案)

TextX支持生成Python静态类型存根(.pyi文件),让Mypy可以静态识别生成的类型:

  1. 将语法保存为单独的.tx文件(比如funl.tx)
  2. 使用TextX命令生成存根:
textx generate funl.tx --target python-stubs
  1. 在代码中导入生成的静态类型:
from funl_stubs import Param

def my_func(param: Param) -> None:
    ...

3. 使用TypeVar结合类型断言

通过typing.TypeVar定义绑定到动态类型的变量,再配合运行时断言确保类型正确性:

from typing import TypeVar

# 绑定到TextX生成的Param类型
ParamType = TypeVar("ParamType", bound=mm["Param"])

def my_func(param: ParamType) -> None:
    # 运行时断言确保类型匹配
    assert isinstance(param, mm["Param"])
    ...

4. 使用TextX的Mypy插件

TextX官方提供了textx-mypy插件,可直接为动态生成的类型提供Mypy支持:

  1. 安装插件:
pip install textx-mypy
  1. 在mypy.ini或pyproject.toml中启用插件:
[mypy]
plugins = textx_mypy

之后即可直接使用mm["Param"]作为类型标注,Mypy会正确识别。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 03:47:21