如何为 C 扩展模块用 mypy 的 stubgen --inspect-mode 生成类型存根?
【免费下载链接】mypyOptional static typing for Python项目地址: https://gitcode.com/GitHub_Trending/my/mypy
当你的 Python 项目引用了一个没有类型信息的 C 扩展模块时,mypy 无法直接处理该模块,会报出类似这样的错误(frobnicate是文档中的示例模块名,下文均以它为例):
core/config.py:7: error: Cannot find implementation or library stub for module named 'frobnicate'mypy 自带的stubgen工具可以通过导入模块并做运行时内省(--inspect-mode)为 C 扩展模块生成.pyi类型存根文件。这篇文章给出完整流程:用stubgen --inspect-mode生成存根草稿,把存根放到 mypy 能找到的位置,再用 mypy 和stubtest验证结果。前提是:mypy 已安装,且该 C 扩展模块能在当前 Python 环境中被正常import(stubgen 默认会导入目标模块,而--no-import明确不支持 C 扩展模块)。
准备条件
安装 mypy(安装后即可使用附带的stubgen命令):
$ python3 -m pip install mypy确认 C 扩展模块可以导入。stubgen 默认会尝试导入目标模块,利用运行时内省为 C 扩展模块生成存根;因此生成存根的 Python 环境必须能 import 该模块。
用 --inspect-mode 生成存根
按模块名生成存根:
$ stubgen --inspect-mode -m frobnicate关键参数说明:
-m MODULE, --module MODULE:按模块名生成存根,可重复使用多次。-m不会递归生成子模块的存根;如果需要递归生成包内所有子模块,改用-p PACKAGE。注意:不能在同一次调用中混合传入文件路径和-m/-p选项。--inspect-mode:导入并内省模块,而不是解析源代码。对 C 模块和仅含 pyc 的包来说这本来就是默认行为,显式加上该参数可以用于强制走内省路径(例如纯 Python 模块中存在动态生成成员的场景)。该参数隐含--no-analysis,因为语义分析需要源代码;--no-analysis本身与--inspect-mode不兼容。-o PATH, --output PATH:修改输出目录。默认输出到./out目录,不存在时自动创建;输出目录中已存在的存根文件会被无警告地覆盖。
可选的增强参数(根据需要在同一条命令中添加):
--doc-dir PATH:解析PATH下的.rst文档来推断更好的函数签名,可能生成更好的存根,但目前仅对 C 扩展模块有效。--include-docstrings:把 docstring 写入存根,包括 C 扩展函数的存根。--include-private:在存根中包含_foo这类单下划线前缀的私有定义。--ignore-errors:某个模块处理过程中抛出异常时,继续处理剩余模块,而不是立即失败。-v, --verbose/-q, --quiet:增加或减少输出信息。
运行完成后,存根会写入out/目录(模块名对应frobnicate.pyi这样的文件名)。需要注意的是:stubgen 生成的是草稿存根,大多数类型默认是Any。对最常用到的 API 手动补充更精确的类型注解,存根才有实际价值。
让 mypy 使用这个存根
生成存根后,mypy 需要能定位到它。文档给出两种方式:
- 把
frobnicate.pyi放到与模块实现相同的目录。同一目录下如果同时存在某模块的.py和.pyi文件,.pyi优先,这样不用改源码就能为模块补充类型信息。 - 把存根集中放在一个专门目录(例如
myproject/stubs),再设置MYPYPATH环境变量指向它:
$ export MYPYPATH=~/work/myproject/stubs也可以在单次运行中临时指定,例如文档中的写法:
$ MYPYPATH=stubs/six mypy ...配置完成后,对引用该 C 扩展模块的代码运行 mypy。此前报出的Cannot find implementation or library stub for module named 'frobnicate'错误应当消失,mypy 会按照存根做类型检查(文档也确认:一旦存在存根,mypy 会像普通类型信息一样检查该存根,# type: ignore注释将被忽略)。
用 stubtest 核对存根与实现的一致性(可选)
stubtest会导入代码、在运行时内省代码对象,再与存根文件比对,指出两者不一致的地方;由于它完全依赖运行时内省,因此对扩展模块特别适用。
$ python3 -m mypy.stubtest frobnicate使用要点(来自 stubtest 文档):
- 运行环境必须能 import 被检查的代码,必要时设置
PYTHONPATH。 - 如果提示找不到存根(类似 "failed to find stubs"),设置
MYPYPATH指向存根目录。 - 如果提示 "not checking stubs due to mypy build errors",需要先解决对应的 mypy 错误 stubtest 才会继续。
- 注意:stubtest 会导入并执行被检查包的 Python 代码。
- 局限:stubtest 不做静态分析,无法判断函数返回类型是否标注准确;类型检查本身仍用 mypy 完成。
限制与注意
--no-import不支持 C 扩展模块:它只用 mypy 的常规搜索机制找源码,并禁用运行时内省(还会导致存根中__all__导出的名字可能不完整)。所以 C 扩展模块的存根生成必须走导入 + 内省路径。- 命令行标志可能在不同版本之间变化,具体可用选项以
stubgen --help为准。 - 存根是草稿,
Any占位需要人工补全;--doc-dir推断更好签名这一优化目前只对 C 扩展模块生效。
参考文档
- stubgen 命令行参考:
--inspect-mode、--no-import、-m/-p、-o等参数定义。 - 存根文件说明:
.pyi的放置方式与MYPYPATH配置。 - stubtest 文档:存根与运行时实现的一致性检查。
- 常见问题的存根示例:
frobnicateC 扩展模块的报错与处理示例。
【免费下载链接】mypyOptional static typing for Python项目地址: https://gitcode.com/GitHub_Trending/my/mypy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考