py.typed 是 stubs 包必需的类型声明文件,缺失会导致 mypy 等工具完全忽略 .pyi 文件;必须置于包根目录、内容为空但不可含 bom 或空格,并在 manifest.in 中显式包含。

stubs 包里为什么 py.typed 文件不能少
没有 py.typed,mypy 或其他类型检查器根本不会读你的 stubs —— 它不是可选的标记,而是开关。Python 3.8+ 要求显式声明包支持类型提示,否则整个包被当作无类型处理。
常见错误现象:mypy 对你写的 .pyi 文件完全无视,报错仍显示 “No library stubs for module X”;或者 VS Code 的 Pylance 显示所有导入都标红,但跳转定义却能进 stub 文件。
- 必须放在 stubs 包根目录(如
types-requests/py.typed),不是子目录下 - 文件内容为空即可,但不能是空格或注释;BOM 字符会导致部分工具识别失败
- 如果用
setuptools打包,确保MANIFEST.in显式包含它:include types_requests/py.typed
如何让 .pyi 文件和源码版本严格对齐
stubs 不是“写一次管三年”,它必须随上游库小版本更新而同步演进。比如 requests 2.31.0 加了 timeout 参数到 Session.request(),你的 types-requests 就得立刻补上对应签名,否则类型检查会漏掉新行为。
使用场景:CI 中跑类型检查时发现大量 false negative(本该报错却没报),往往是因为 stubs 比运行时库旧了。
立即学习“Python免费学习笔记(深入)”;
家政服务平台系统包含家用电器安装清洗、搬家、家电维修、管道疏通、月嫂保姆、育儿陪护、上门开锁等多种服务项目,用户可以直接通过家政小程序咨询,在线预约服务类型,同时还设置有知识科普,给用户科普一些清洁保养小技巧,让用户能够足不出户就可以直接预约服务,方便又快捷。本项目使用微信小程序平台进行开发。使用腾讯专门的小程序云开发技术,云资源包含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需
- 别手动维护版本映射表——用
stubgen+ 差分比对:先用stubgen -p requests==2.31.0生成快照,再和当前 stubs 做diff - 在
setup.py或pyproject.toml里通过requires-dist声明兼容范围,例如"requests >=2.28.0, - 避免在 stubs 里写
sys.version_info >= (3, 9)这类运行时判断——.pyi是静态契约,条件逻辑应由上游决定
mypy 报 Cannot find implementation or library stub for module X 怎么快速定位
这个错误不一定是 stubs 缺失,更可能是路径、命名或安装方式出了问题。mypy 查找 stubs 的优先级是:本地 typings/ 目录 → site-packages 里的 types-* 包 → typeshed 主干。
典型陷阱:你装了 types-urllib3,但项目里 import 的是 urllib3.contrib.socks,而该子模块在 stubs 包里没被覆盖,就会触发此报错。
- 运行
mypy --show-traceback your_file.py看具体卡在哪一行 import - 用
python -c "import types_urllib3; print(types_urllib3.__file__)"确认 stubs 是否真被加载 - 检查包名是否匹配:第三方 stubs 必须叫
types-xxx,且xxx是 PyPI 上原包的准确名字(注意连字符 vs 下划线) - 若用 Poetry,确认
types-xxx在[tool.poetry.dependencies]下,而非dev-dependencies—— mypy 默认只扫主依赖
自动生成 stubs 后为什么还得人工修 overload 和泛型
stubgen 能搞定函数签名和字段,但对重载、协议实现、高阶泛型几乎无能为力。比如 functools.cached_property 在不同 Python 版本中返回类型不同,stubgen 只会输出最宽泛的 Any,而正确 stub 应用 @overload 分情况声明。
性能影响:错用泛型约束(如把 TypeVar("T", bound="str") 写成 bound=str)会导致 mypy 类型推导变慢,甚至卡死。
- 遇到
Union堆砌或Any泛滥的生成结果,优先查 upstream 的 typing 注解或文档中的类型描述 -
Callable[..., T]要小心:省略号不代表任意参数,而是表示“参数类型未指定”,应尽量还原为具体形参列表 - 协议(
Protocol)相关 stub 必须手写,stubgen完全不识别__protocol__ = True或结构化匹配逻辑
最麻烦的从来不是写 stub,而是验证它有没有悄悄放过本该捕获的类型错误。每次发布前,拿几个典型业务代码片段跑一遍 mypy —— 别信生成结果,信运行时实际行为。






