Python之stubmaker包语法、参数和实际应用案例

 更新时间:2026年06月24日 09:00:40   作者:王国平  
stubmaker 是 Python 官方配套的存根文件(.pyi)自动生成工具,底层封装 inspect、typing、ast 模块,用于为已有 Python 源码、第三方编译扩展库、动态模块生成类型提示存根文件,下面就来详细的介绍一下

一、stubmaker 概述与核心功能

1. 什么是 stubmaker

stubmaker 是 Python 官方配套的存根文件(.pyi)自动生成工具,底层封装 inspecttypingast 模块,用于为已有 Python 源码、第三方编译扩展库(C/C++/Rust 编写的 .so/.pyd)、动态模块生成类型提示存根文件(Stub File)。

区分同类工具:

  • stubgen:内置工具,仅支持纯 Python 源码;无法解析二进制扩展库;
  • stubmaker:增强版,兼容纯 Python + 编译扩展模块,自动推导函数签名、类属性、泛型、异常抛出,生成规范 .pyi 类型提示文件,适配 VSCode/PyCharm/mypy 静态类型检查。

2. 核心功能

  1. 纯Python源码批量生成存根:扫描文件夹/单文件,自动解析函数参数、返回值、类字段、装饰器;
  2. 二进制扩展库存根生成:解析 .pyd/.so 动态库、Cython 模块,弥补 stubgen 无法处理编译模块的短板;
  3. 类型自动推导:识别基础类型、Union、Optional、List/Dict、泛型、TypeVar;
  4. 导出完整模块结构:导出 __all__、常量、枚举、内置异常、类继承关系;
  5. 自定义过滤规则:忽略私有函数、过滤指定模块、保留/删除注释;
  6. 增量生成:对比旧 .pyi 文件,仅更新变更部分,不覆盖手写类型注释;
  7. mypy 兼容:生成符合 PEP484/PEP561 标准存根,支持静态类型校验。

二、安装方式

方式1:pip 标准安装

pip install stubmaker
# 带类型检查依赖(推荐)
pip install stubmaker mypy typing-extensions

方式2:源码安装(最新开发版)

git clone https://github.com/osandov/stubmaker.git
cd stubmaker
pip install .

依赖要求

  • Python ≥3.7;
  • 可选依赖:mypy(类型校验)、cython(解析Cython模块)、setuptools(解析扩展库元数据)。

三、命令行语法、全局参数、子命令参数

基础命令语法

stubmaker [全局参数] 子命令 [子命令参数] 目标路径

支持两大核心子命令:generate(生成存根)、check(校验已有存根合法性)

1. 全局通用参数

参数作用
-h/--help全局帮助文档
-v/--verbose输出详细日志,打印解析每个函数/类的过程
-q/--quiet静默模式,仅输出报错
--python-exec PATH指定解析用Python解释器(用于多版本环境)
--cache-dir DIR设置模块解析缓存目录,加速重复生成

2. generate 子命令(核心生成命令)完整参数

stubmaker generate [OPTIONS] TARGET
参数说明
-o/--output DIR指定 .pyi 输出目录,默认和源码同目录
--recursive/-r递归扫描文件夹,批量生成子模块存根
--ignore-private跳过下划线开头私有方法/变量(_func, __attr)
--include-docstrings将源码docstring写入存根文件
--no-types-eval关闭运行时类型推导,仅通过AST静态解析(安全,避免执行恶意代码)
--module-filter REGEX正则过滤模块,只生成匹配模块的存根
--exclude REGEX排除匹配正则的文件/模块
--incremental增量更新,不覆盖手动修改的.pyi
--force强制覆盖所有旧存根文件
--stub-extension SUFFIX自定义存根后缀,默认 .pyi
--add-type-imports自动补充 typing 模块导入(Optional, List, Any等)
--skip-constants不生成模块常量存根
--export-all自动生成 __all__ 列表,导出所有公有对象

3. check 子命令(存根校验)参数

stubmaker check [OPTIONS] STUB_FILE
参数作用
--strict严格校验,类型不匹配直接报错
--mypy-config FILE指定mypy配置文件校验存根

4. Python 代码内调用API语法(可编程生成)

stubmaker 提供编程式接口,可嵌入脚本批量自动化生成:

from stubmaker import StubGenerator, GeneratorConfig

# 配置类
config = GeneratorConfig(
    recursive=True,
    ignore_private=True,
    output_dir="./stubs",
    incremental=True
)
# 初始化生成器
gen = StubGenerator(config=config)
# 生成单文件
gen.generate_file("mylib/main.py")
# 生成整个包
gen.generate_package("mylib/")
# 校验存根
gen.check_stub("stubs/main.pyi")

四、8个完整可运行实战应用案例

案例1:为单个纯Python文件生成基础存根

场景:给项目单文件 utils.py 生成 utils.pyi,输出到同目录,忽略私有方法。
命令行:

stubmaker generate --ignore-private utils.py

生成效果:自动提取所有公有函数、类,推导参数/返回值类型,生成标准 .pyi

案例2:递归批量为整个项目包生成存根(输出至独立stubs文件夹)

场景:项目包名 myproject/,递归扫描所有子模块,存根统一输出到 ./stubs,增量更新。

stubmaker generate -r -o ./stubs --incremental --export-all myproject/

代码API版本:

from stubmaker import StubGenerator, GeneratorConfig
cfg = GeneratorConfig(recursive=True, output_dir="./stubs", incremental=True, export_all=True)
gen = StubGenerator(cfg)
gen.generate_package("./myproject")

案例3:解析Cython编译扩展.pyd二进制模块生成存根

场景:第三方Cython库 fastcalc.pyd,stubgen无法解析,使用stubmaker运行时解析二进制导出符号。

stubmaker generate --python-exec python3 fastcalc.pyd -o ./stubs

关键:不加 --no-types-eval,必须运行加载模块读取运行时签名。

案例4:过滤指定模块、排除测试文件

场景:项目过滤 core.* 模块,排除所有 test_*.py 文件,不生成测试存根。

stubmaker generate -r --module-filter "^core\." --exclude "test_.*" src/

案例5:生成带文档注释、完整类型导入的标准化存根

场景:生成可发布给第三方的规范存根,保留docstring、自动补全typing导入。

stubmaker generate --include-docstrings --add-type-imports --force src/api.py -o dist/stubs

案例6:安全静态解析(禁止执行源码,防恶意代码)

场景:解析外部不可信第三方源码,关闭运行时类型求值,仅用AST静态分析。

stubmaker generate --no-types-eval untrusted_lib.py

限制:无法解析动态赋值类型、二进制扩展库,仅纯静态语法树解析。

案例7:自动化脚本打包时生成存根(setup.py集成)

场景:打包发布Python库时,自动构建stubs并打包进分发包。
build_stubs.py 脚本:

from stubmaker import StubGenerator, GeneratorConfig
import os
def build_package_stubs():
    cfg = GeneratorConfig(
        recursive=True,
        output_dir="./build/stubs",
        ignore_private=True,
        export_all=True
    )
    gen = StubGenerator(cfg)
    gen.generate_package("./mypackage")
    print("存根生成完成,路径:", os.path.abspath("./build/stubs"))
if __name__ == "__main__":
    build_package_stubs()

执行:python build_stubs.py,配合 setup.pycmdclass 自动构建。

案例8:校验已手写存根与源码类型一致性

场景:手动修改过 .pyi,校验是否和源码函数签名、类型匹配,严格模式报错阻断发布。

stubmaker check --strict stubs/core.pyi --mypy-config mypy.ini

脚本API校验:

from stubmaker import StubGenerator, GeneratorConfig
gen = StubGenerator(GeneratorConfig())
result = gen.check_stub("./stubs/core.pyi", strict=True)
if not result.success:
    raise SystemExit("存根与源码类型不匹配")

五、常见错误、报错原因与解决方案

错误1:ModuleNotFoundError: No module named ‘stubmaker’

  • 原因:未安装包、pip环境与运行Python解释器不匹配;
  • 解决:
# 确认当前pip绑定当前python
python -m pip install stubmaker

错误2:Failed to load module xxx.pyd / segmentation fault when parsing extension

  • 原因1:Python版本与编译扩展库版本不兼容(32/64位、3.8 vs 3.10);
  • 原因2:扩展库依赖系统动态库缺失(Windows缺少VC++运行库、Linux缺少glibc);
  • 解决:使用对应版本解释器 --python-exec,安装系统依赖,或切换静态解析 --no-types-eval(仅纯py文件)。

错误3:Type evaluation disabled, cannot process binary module

  • 原因:使用 --no-types-eval 参数同时解析 .pyd/.so 扩展;静态AST无法读取二进制导出符号;
  • 解决:移除 --no-types-eval,允许运行时加载模块解析。

错误4:Stub file not updated with --incremental but source changed

  • 原因:增量模式会跳过手动修改过的 .pyi 文件,不会覆盖手写代码;
  • 解决:需要全量更新时加 --force 参数强制覆盖。

错误5:SyntaxError in generated .pyi, invalid type annotation

  • 原因1:源码存在动态复杂类型(动态生成类、元编程),自动推导出错;
  • 原因2:旧Python版本不支持PEP604 | 联合类型;
  • 解决:手动修正对应存根,或添加 --skip-constants 过滤动态常量,升级Python到3.10+。

错误6:Recursive scan not working, subfolder stubs missing

  • 原因:忘记加 -r/--recursive 参数,仅处理顶层文件;
  • 解决:命令行追加 -r,API配置 recursive=True

错误7:ImportError: cannot import name ‘StubGenerator’ from ‘stubmaker’

  • 原因:stubmaker版本过低,早期版本无编程API;
  • 解决:升级到最新版 pip install --upgrade stubmaker

错误8:Mypy check reports “Missing type annotation” in generated stubs

  • 原因:源码无类型注解,stubmaker自动推导为 Any
  • 解决:源码补充基础类型注解,或生成时手动修改存根,添加显式类型。

六、使用注意事项

1. 安全风险

  • 默认模式会导入目标模块执行代码以获取运行时类型,不要用默认参数解析未知/恶意第三方代码;处理不信任源码必须加 --no-types-eval
  • 解析二进制扩展库会加载本地动态库,存在崩溃风险,建议隔离虚拟环境操作。

2. 类型推导局限性

  • 高度元编程、动态创建函数/类、工厂模式无法100%精准推导,生成后需人工校对;
  • 运行时动态修改的属性、 monkey patch 不会出现在存根中;
  • 复杂泛型、自定义TypeVar可能推导为Any,需手动修正。

3. 项目工程规范

  • 生产项目建议将 .pyi 存根统一放入独立 stubs/ 目录,不要和源码混杂;
  • 发布开源库时,将生成的 .pyi 打包分发,搭配 py.typed 文件(PEP561)告知类型检查器存在存根;
  • 版本迭代时使用 --incremental 保护手写的精细类型注释。

4. 性能优化

  • 开启 --cache-dir 缓存模块解析信息,多次生成大幅提速;
  • 大型项目配合 --exclude 过滤测试、第三方依赖、文档目录,减少扫描耗时。

5. 编辑器兼容

  • VSCode/PyCharm识别 .pyi 需确保输出目录加入 sys.path
  • 若IDE不读取生成存根,在项目根目录创建 py.typed 空文件。

6. 版本兼容提醒

  • Python3.7及以下不支持 | 联合类型,生成存根会使用 Union[] 兼容写法;
  • 低于0.10版本的stubmaker不支持递归批量生成,建议升级至0.12+稳定版。

到此这篇关于Python之stubmaker包语法、参数和实际应用案例的文章就介绍到这了,更多相关Python stubmaker包应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Python和wxPython构建自动化Node.js项目管理工具

    基于Python和wxPython构建自动化Node.js项目管理工具

    在前端或 Node.js 开发过程中,开发者经常需要管理大量的项目文件夹,本文介绍了一款基于Python和wxPython开发的桌面工具,旨在提升前端和Node.js开发效率,希望对大家有所帮助
    2026-01-01
  • 简单了解Java Netty Reactor三种线程模型

    简单了解Java Netty Reactor三种线程模型

    这篇文章主要介绍了简单了解Java Netty Reactor三种线程模型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • Python+Selenium实现一键摸鱼&采集数据

    Python+Selenium实现一键摸鱼&采集数据

    将Selenium程序编写为 .bat 可执行文件,从此一键启动封装好的Selenium程序,省时省力还可以复用,岂不美哉。所以本文将利用Selenium实现一键摸鱼&一键采集数据,需要的可以参考一下
    2022-08-08
  • 使用 Python 解析配置文件格式

    使用 Python 解析配置文件格式

    选择配置格式是一种微妙的权衡。但是,一旦你做出决定,Python 就可以使用少量代码来解析大多数流行的格式。今天通过本文给大家分享 Python 解析配置文件格式的问题,感兴趣的朋友一起看看吧
    2021-07-07
  • 分享一下Python数据分析常用的8款工具

    分享一下Python数据分析常用的8款工具

    Python是数据处理常用工具,可以处理数量级从几K至几T不等的数据,具有较高的开发效率和可维护性,还具有较强的通用性和跨平台性,这里就为大家分享几个不错的数据分析工具,需要的朋友可以参考下
    2018-04-04
  • 全面了解python中的类,对象,方法,属性

    全面了解python中的类,对象,方法,属性

    下面小编就为大家带来一篇全面了解python中的类,对象,方法,属性。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • PyTorch变分自编码器的构建与应用小结

    PyTorch变分自编码器的构建与应用小结

    变分自编码器是一种强大的深度学习模型,用于学习数据的潜在表示并能生成新的数据点,使用PyTorch实现VAE不仅可以加深对生成模型的理解,还可以利用其灵活性进行各种实验,这篇文章主要介绍了PyTorch变分自编码器的构建与应用,需要的朋友可以参考下
    2024-07-07
  • Python身份运算符(is/is not)与双等号的区别详解

    Python身份运算符(is/is not)与双等号的区别详解

    身份运算符(is/is not)与双等号的区别是Python编程中的核心知识点之一,掌握这项技能对于提升编程效率和应用效果至关重要,本文通过代码示例给大家介绍的非常详细,需要的朋友可以参考下
    2026-05-05
  • Django实现翻页的示例代码

    Django实现翻页的示例代码

    翻页是经常使用的功能,Django提供了翻页器。用Django的Paginator类实现,有需要了解Paginator类用法的朋友可参考。希望此文章对各位有所帮助
    2021-05-05
  • Python基于更相减损术实现求解最大公约数的方法

    Python基于更相减损术实现求解最大公约数的方法

    这篇文章主要介绍了Python基于更相减损术实现求解最大公约数的方法,简单说明了更相减损术的概念、原理并结合Python实例形式分析了基于更相减损术实现求解最大公约数的相关操作技巧与注意事项,需要的朋友可以参考下
    2018-04-04

最新评论