将一个pyi(类型存根文件)导入到普通的Python模块中

12

我有一个类似于宏的程序,运行在一个父程序中,并从该程序中导入 API 模块(我们称其为foo)。问题是该模块仅存在于该程序中,因此我无法像在软件外部运行pydocmd一样执行操作,因为脚本会抛出ReferenceError。为了方便自己的开发,我创建了一个类型桩文件 foo.pyi 在我的项目目录中。我想要做的是,如果导入失败,则将该类型桩作为普通 Python 文件导入,以提供虚拟函数和属性。类似于:

try:
  from foo import api
except ImportError:
  # Fallback to the type stub file.
  import foo as api  # type: ignore[attr-defined]
try:
  import foo
except ImportError:
  from . import foo.pyi

然而,这会引发一个错误,因为它试图从项目文件夹中不存在的foo库导入pyi。我能想到的唯一其他选择是将.pyi文件的完全相同副本命名为"dummy_foo.py",但那样我必须在一个仓库中维护两个相同文件的副本。我宁愿不这样做。


我也想知道如何做到这一点。 - Jgd10
你能详细解释一下存根文件吗?这些通常用于类型提示,但你的问题让人感觉里面有实际逻辑?只要我理解正确,我有一个相当好的解决方案。在回答之前,我只想确保我理解得正确。如果你能在问题中添加一个最小可重现示例(对于未来的访问者也很有帮助),那将非常有帮助。 - exhuma
尝试访问 https://dev59.com/anVD5IYBdhLWcg3wKYP-#43602557 - Andrew
2个回答

2
我发现了这个问题,但我的问题是关于类型检查的。在我的情况下,pyi文件包含类定义(因此类型提示有效),但库没有。解决方案是检查typing.TYPE_CHECKING
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from library import _PrivateClass

def foo(x: "_PrivateClass"):
    ...

from __future__ import annotations 提供了一种很好的方式,请参考这里 - undefined

1

我之前写过这个,我认为它仍然有效:

import importlib


def import_stub(stubs_path, module_name):
    sys.path_hooks.insert(0,
        importlib.machinery.FileFinder.path_hook(
            (importlib.machinery.SourceFileLoader, ['.pyi']))
    )
    sys.path.insert(0, stubs_path)
    
    try:
        return importlib.import_module(module_name)
    finally:
        sys.path.pop(0)
        sys.path_hooks.pop(0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接