我目前使用的 Python 库 (
x
) 不带有类型提示。我选择为我在项目中使用的 x
方法添加存根文件,如下所示:
MyProject_1/
stubs/
x/
__init__.pyi # Contains type hints for any attributes of `x`.
package_1/
package_1_main.py # Imports `x`.
__init__.py
py.typed # Indicates package 1 type hints are specified inline.
setup.py # Specifies `x` as a dependency under `install_requires` and `py.typed` under `package_data`.
然后在
MyProject_1
目录中,我运行 MYPYPATH=stubs mypy .
。
如果
package_1_main.py
导入 x
,则 mypy
成功键入提示 x
基于 stubs/x
导入。这里一切都很好。
现在我已经制作了另一个项目
MyProject_2
,它依赖于MyProject_1
My_Project_2
成功地使用了package_1_main.py
中指定的内联类型提示,因为py.typed
下的package_1
。
问题是
MyProject_2
无法识别 stubs/x
。由于 x
是 MyProject_2
到 MyProject_1
的传递依赖,因此我能够在 x
中使用 MyProject_2
。但是,这没有 stubs/x
下指定的类型提示。
我可以想象有 3 种方法可以使用这些存根(从而访问
x
的类型提示):
在
stubs
中运行MyProject_1
时,将MYPYPATH
下的mypy .
目录添加到MyProject_2
中。这样做的缺点是,它取决于如何通过 MyProject_1
安装 pip
,并且 stubs
必须作为 setup.py
中分布式包数据的一部分。
将
stubs
下的MyProject_1
目录复制到MyProject_2
,手动保持同步。这样做的缺点是维护开销。
创建第三个项目,名为
MyProject_Stubs
,专门用于保存依赖于 x
的任何项目的存根文件,无论是传递还是直接。这样做的缺点是一个专门用于存根的项目。
我还可以考虑其他方法吗?对于稍微固执己见的部分:这些方法中哪一种似乎具有最大的净优势?
据我所知,没有办法传递性地共享存根。
相反,您必须专注于寻找使您的存根可用于两个项目/使其成为两个项目的依赖项的方法。
大约有六种不同的方法可以做到这一点,我将按照大致递增的顺序列出这些方法。
将存根存储在本地计算机上的某个位置,并让您的两个项目通过 MYPYPATH 环境变量或配置文件选项引用它。
这相对简单,但缺点是您的项目只能在本地计算机上运行。如果您计划让其他人使用此项目,他们将需要获取您的存根并设置他们的 MYPYPATH。
将您的存根复制到第二个项目。正如您所说,这里的主要缺点是您现在需要手动保持存根同步。
为您的存根创建一个单独的 git 存储库,并将它们作为 git 子模块添加到您的两个项目中。
这解决了选项 2 的代码重复问题。唯一真正的缺点是,每次更新存根存储库时,您需要记住在两个项目中碰撞子模块引脚。
将项目的类型提示贡献给 typeshed Python 类型提示存储库,然后等待下一个 mypy 版本或使用
--custom-typeshed-dir
标志/配置选项运行 mypy。
请注意,Typeshed 接受部分存根,并希望在未来某个时间切换到更加迭代和快速的发布节奏。
如果您想广泛开源您的工作,但不一定希望在开源后承担维护存根的负担,那么此选项将是最好的。
主要缺点是你无法立即解锁自己。
使用
X-stubs
文件创建 py.typed
包。这有点像您的选项 3,只不过您的新项目明确仅用于项目 X 的存根并且是开源的。
然后,您可以将
X-stubs
包添加到 pip 依赖项中,就像任何 pip 包一样,甚至最终可能会考虑更广泛的开源和分发它们。
这与您的选项 3 基本相同,只是您的包的名称不同并且不太特定于您的项目。
向项目 X 提交拉取请求,添加 py.typed 文件以及一些类型提示,并说服他们落地它。
当然,说起来容易做起来难——当然,并非所有项目都愿意接受类型提示,因为这可能会增加他们的维护负担。
如果您只关心自己解锁,我会选择选项 1-3。如果您还想尝试开源您的工作并帮助改善 Python 类型生态系统,那么其他选项更适合。
我会避免使用你的选项 1——它似乎涉及与我的选项 3 和 5 大致相同的设置工作量,同时还需要在项目 2 中进行更多工作才能使用。