如何判断 Python 模块是否是命名空间模块

Nat*_*ley 6 python namespaces module python-3.x

在 Python 3 中,模块可以是没有命名空间模块__init__.py(根据PEP 420)或作为常规模块(即“[modules] 包,因为它们在 Python 3.2 及更早版本中实现” - PEP 420)具有一个__init__.py或 是单个.py文件。

如何区分命名空间模块和“普通”模块?

(我使用的是 Python 3.5.3)

例如命名空间模块命名mod打印为:

(Pdb) mod
<module 'mymodule' (namespace)>
Run Code Online (Sandbox Code Playgroud)

和普通模块打印为:

(Pdb) mod
<module 'mymodule' from '/path/to/mymodule/__init__.py'>
Run Code Online (Sandbox Code Playgroud)

use*_*ica 6

命名空间包有一个__path__, 并且__file__设置为None或没有__file__属性。(在Python 3.7 及更高版本__file__设置为;之前未设置。)None

if hasattr(mod, __path__) and getattr(mod, '__file__', None) is None:
    print("It's a namespace package.")
Run Code Online (Sandbox Code Playgroud)

相反,不是包的模块没有__path__,并且不是命名空间包的包已__file__设置为其__init__.py.

  • @NathanaelFarley:包有一个 `__path__`,但非包模块没有。`__path__` 检查是为了区分命名空间包和内置模块(如 `sys`),后者也没有 `__file__`。 (2认同)

fse*_*art 5

Python 3.8 文档中__file__是:

加载模块的位置的名称,例如内置模块的“builtin”和从源加载的模块的文件名。通常应该设置“origin”,但它可能是 None (默认值),表示它是未指定的(例如,对于命名空间包)。

另外,正确答案应该是:

is_namespace = (
    lambda module: hasattr(module, "__path__")
    and getattr(module, "__file__", None) is None
)
Run Code Online (Sandbox Code Playgroud)