python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python stubmaker包应用

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

作者:王国平

stubmaker 是 Python 官方配套的存根文件(.pyi)自动生成工具,底层封装 inspect、typing、ast 模块,用于为已有 Python 源码、第三方编译扩展库、动态模块生成类型提示存根文件,下面就来详细的介绍一下

一、stubmaker 概述与核心功能

1. 什么是 stubmaker

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

区分同类工具:

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 .

依赖要求

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

基础命令语法

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
python -m pip install stubmaker

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

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

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

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

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

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

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

六、使用注意事项

1. 安全风险

2. 类型推导局限性

3. 项目工程规范

4. 性能优化

5. 编辑器兼容

6. 版本兼容提醒

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

您可能感兴趣的文章:
阅读全文