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

如何规避stubtest的「类型别名在运行时不存在」错误?

关于stubtest检测类型别名缺失的问题

示例

给定实现文件 ./mylib/minimalistic_repro.py:

class Foo:
    def __init__(self, param):
        self.param = param

class Bar:
    def __init__(self, param):
        self.param = param

def foobar(par1, par2):
    return par1.param + par2.param

对应的存根文件 ./mylib/minimalistic_repro.pyi:

from typing import TypeAlias

FooBar: TypeAlias = Foo | Bar

class Foo:
    param: int
    def __init__(self, param: int) -> None: ...

class Bar:
    param: int
    def __init__(self, param: int) -> None: ...

def foobar(par1: FooBar, par2: FooBar) -> int: ...

注意存根文件第三行的类型别名定义:FooBar: TypeAlias = Foo | Bar

当前执行情况:

  • mypy --strict mylib、flake8 mylib 和 ruff check --select E,F,B,SIM 均检测通过
  • 运行 python -m mypy.stubtest mylib 时,报错:error: mylib.minimalistic_repro.FooBar is not present at runtime

临时解决方案:使用stubtest的允许列表(通过stubtest --generate-allowlist生成)

问题

  1. 是否有更优方法规避该错误?
  2. 我的实现方式是否存在根本性错误?
  3. 若不存在,是否值得提交功能请求?

已尝试的其他方案

  1. 直接在函数签名中写 def foobar(par1: Foo | Bar, par2: Foo | Bar),但实际任务是为第三方PyPI包编写类型提示,需要合并多达18种类型,这种写法过于繁琐不可行。
  2. 将FooBar类型别名定义放在.py文件(如tp_aliases.py)中再导入,虽然能让示例通过stubtest,但实际场景中tp_aliases.py不属于目标包,无法采用。

解答

1. 更优的规避方法

可以利用TYPE_CHECKING常量将类型别名标记为仅用于类型检查,避免stubtest检测其运行时存在性:

修改后的存根文件:

from typing import TypeAlias
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    FooBar: TypeAlias = Foo | Bar

class Foo:
    param: int
    def __init__(self, param: int) -> None: ...

class Bar:
    param: int
    def __init__(self, param: int) -> None: ...

def foobar(par1: "FooBar", par2: "FooBar") -> int: ...

关键细节:

  • TYPE_CHECKING在运行时始终为False,因此包裹的类型别名不会被视为需要在运行时存在的符号
  • 函数签名中的FooBar需要用字符串引号包裹(或导入from __future__ import annotations),因为全局作用域中并未定义该别名,仅在类型检查阶段可见

2. 实现方式是否有根本性错误?

没有根本性错误。类型别名本身就是类型检查工具专属的语法,不需要在运行时存在——存根文件的核心作用是提供类型信息,而非运行时代码。stubtest的报错源于其默认行为:未区分“运行时可见符号”和“仅类型检查用符号”,误将类型别名纳入了运行时存在性的检测范围。

3. 是否值得提交功能请求?

值得提交。stubtest应该默认识别并忽略用TypeAlias定义的别名,或提供配置选项跳过这类仅用于类型检查的符号。当前的允许列表方案只是临时 workaround,对于需要大量类型别名的场景(如你提到的18种类型合并),维护允许列表会非常繁琐。

你可以在mypy的GitHub仓库提交issue,说明场景:为第三方包编写存根时,需要用类型别名简化签名,但stubtest误报运行时缺失,希望工具能自动识别TypeAlias并跳过检测,或添加专属参数排除这类符号。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:15:13