.pyi
文件是 Python 的存根文件(Stub Files),用于为 Python 模块提供类型提示信息(Type Hints),而不影响运行时的行为。它是 Python 类型系统(PEP 484、PEP 526 等)的一部分,主要用于支持静态类型检查工具如 mypy
、PyCharm、VS Code 等 IDE 的智能提示和类型分析。
📌 .pyi
文件的作用
-
分离类型信息与实现代码
- 可以将类型注解从运行时代码中分离出来,避免污染
.py
文件。 - 特别适用于遗留项目或 C 扩展模块(如标准库中的
os.pyi
、sys.pyi
)。
- 可以将类型注解从运行时代码中分离出来,避免污染
-
支持第三方库的类型提示
- 如果某个库本身没有提供类型提示,可以通过
.pyi
文件为其添加类型信息。 - 例如:
typeshed
项目就是 Python 官方维护的一个大型.pyi
存储库,包含了标准库和一些内置模块的类型信息。
- 如果某个库本身没有提供类型提示,可以通过
-
提高可维护性
- 在团队开发中,使用
.pyi
文件可以更容易地管理和版本控制类型信息。
- 在团队开发中,使用
🧱 .pyi
文件的结构
.pyi
文件的语法与普通 .py
文件非常相似,但只包含函数签名、类定义、变量类型等类型信息,不包含实际的实现逻辑。
示例:
原始 .py
文件:
# my_module.py
def greet(name):
print(f"Hello, {name}")
对应的 .pyi
文件:
# my_module.pyi
def greet(name: str) -> None: ...
注意:
- 使用
...
表示该函数没有实际体(即只是声明)。 - 所有变量、函数、类都必须带有类型信息。
✅ .pyi
文件的命名和位置
- 通常与对应的
.py
文件同名,扩展名为.pyi
。 - 放在与
.py
文件相同目录下,或者放在特定的类型目录中(如stubs/
)。 - 当使用类型检查器(如
mypy
)时,会自动查找并加载这些文件。
🔍 示例:为类添加类型信息
.py
文件:
# person.py
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print(f"Hello, I'm {self.name}")
.pyi
文件:
# person.pyi
class Person:
name: str
age: int
def __init__(self, name: str, age: int) -> None: ...
def say_hello(self) -> None: ...
🛠️ 如何使用 .pyi
文件
-
安装类型检查工具(如 mypy)
pip install mypy
-
运行类型检查
mypy my_module.py
mypy
会自动读取同目录下的.pyi
文件进行类型检查。 -
IDE 支持
- VS Code(配合 Pylance)
- PyCharm
- 其他现代 Python 编辑器都支持
.pyi
文件中的类型提示。
🧩 更复杂的例子(含泛型、协议等)
# example.pyi
from typing import List, TypeVar, Protocol
T = TypeVar("T")
class HasLength(Protocol):
def __len__(self) -> int: ...
def process(items: List[T]) -> T: ...
def get_length(obj: HasLength) -> int: ...
📅 关键时间线
时间 | 版本 | 事件 |
---|---|---|
2014 年 | N/A | PEP 484 提案开始讨论,提出使用类型提示的标准方式,并首次提到使用 .pyi 存根文件用于分离类型信息与实现。 |
2015 年 9 月 | Python 3.5 | PEP 484 被接受并合入 Python 3.5,这是类型提示正式进入 Python 的起点。虽然 .pyi 不是语言特性本身的一部分,但它是 PEP 484 推荐的用法之一。 |
2016 年 | mypy 0.4.x+ | mypy 等静态类型检查工具开始广泛支持 .pyi 文件。 |
2017 年 | Python 3.6 | PEP 526 引入变量注解语法(如 x: int = 1 ),进一步丰富了类型系统生态,也增强了 .pyi 文件的能力。 |
2018 年 | PEP 561 | PEP 561 正式规范了如何为第三方库打包和分发类型信息(通过 .pyi 文件或 Typed 包标记)。这是 .pyi 文件被正式纳入生态系统标准的重要一步。 |
✅ 支持 .pyi
文件的 Python 版本
虽然 .pyi
文件不是 Python 解释器直接使用的功能(它们主要用于类型检查工具),但为了使用完整的类型提示语法,推荐使用以下版本:
功能 | 建议最低 Python 版本 |
---|---|
基础类型提示(函数参数、返回值) | Python 3.5 |
变量注解(PEP 526) | Python 3.6 |
支持 from typing import * 的完整特性 | Python 3.5+ |
支持 TypedDict 、Protocol 等高级特性 | Python 3.8(通过 typing_extensions 可向后兼容) |
PEP 561(发布类型信息包) | Python 3.5+(工具支持为主) |
🧩 工具对 .pyi
的支持
工具 | 是否支持 .pyi |
---|---|
mypy | ✅ 完全支持 |
pyright / Pylance (VS Code) | ✅ 完全支持 |
PyCharm | ✅ 支持良好 |
pytype (Google) | ✅ 支持 |
Jedi (代码补全) | ⚠️ 部分支持 |
🔚 总结
问题 | 回答 |
---|---|
.pyi 是从哪个 Python 版本开始支持的? | 没有具体“开始支持”的版本,它是随类型提示(PEP 484)一起出现的,Python 3.5 是第一个支持完整类型提示语法的版本。 |
我应该使用哪个 Python 版本来配合 .pyi ? | 推荐使用 Python 3.9 或更高版本,以获得最全面的类型系统支持。 |
.pyi 是官方支持的吗? | 是的,PEP 561 正式将其纳入 Python 生态系统标准。 |