Python中.pyi文件与.py文件的区别及.pyi应用场景咨询
.pyi 与 .py 文件的核心区别及实用说明
核心区别
- 功能定位不同:
.py是Python的可执行源码文件,包含完整的业务实现、变量/函数/类的完整逻辑,会被Python解释器直接加载执行。.pyi是Python类型存根文件,仅包含接口定义、类型标注,没有实际执行逻辑,也不会被解释器在运行时加载。 - 作用对象不同:
.py面向运行时和所有开发者,是项目功能的核心载体。.pyi面向静态类型检查工具(如mypy、pyright)和IDE的补全/提示功能,仅用于提供类型信息。 - 类型优先级不同:同目录下存在同名的
.py和.pyi文件时,静态类型检查工具会优先读取.pyi中的类型定义,自动忽略.py文件自带的类型标注。
项目开发中可以正常使用.pyi文件
日常开发中完全可以根据需求引入.pyi文件,常见适用场景包括:
- 给非Python实现的扩展包补充类型:比如用C/C++/Rust开发的Python扩展,无法直接在源码中编写Python语法的类型标注,通过配套的.pyi文件即可给用户提供完整的IDE补全和静态类型检查支持。
- 给无类型标注的第三方旧包补充类型:部分未做类型适配的第三方依赖,会导致静态检查工具抛出大量无意义的类型错误,自行编写对应依赖的.pyi存根文件即可解决这类问题。
- 分离对外接口类型与内部实现类型:内部实现的类型标注可能包含大量内部细节,希望对外暴露的接口使用更简洁的类型定义时,可单独通过.pyi文件定义对外的公共接口类型。
.pyi具备的.py无法实现的实用功能
- 类型定义与业务实现完全解耦:不需要修改原有
.py的业务代码,就能补充或覆盖类型定义,避免大量复杂类型标注污染业务逻辑代码。 - 为动态生成的接口提供类型支持:对于运行时动态生成的模块、monkey patch修改的接口、动态注入的方法等场景,无法直接在原有源码上加类型标注,
.pyi是目前官方标准的唯一类型标注解决方案。 - 完全消除类型标注的运行时开销:虽然Python的类型标注本身运行时开销极低,但部分复杂的泛型、条件类型需要导入额外的typing相关模块,写在
.py中会产生额外的导入开销,放在.pyi中的内容运行时完全不会加载,零额外开销。
内容的提问来源于stack exchange,提问作者NoneType
相关产品推荐
相关产品推荐

