【问题标题】:Relative import of a module within a package包内模块的相对导入
【发布时间】:2016-11-24 00:16:56
【问题描述】:

我怎样才能使模块内的模块.adipiscing.lorem_ipsum 可用,以一种干净地使用导入系统并且不会留下无关名称未使用?

给定一个代码库:

foo/
    consecteur.py
    adipiscing/
        lorem_ipsum.py

consecteur 模块需要访问adipiscing.lorem_ipsum 模块。

这就是我想做的:

# consecteur.py

from . import adipiscing.lorem_ipsum

dolor = adipiscing.lorem_ipsum.dolor_sit_amet()

这行不通; from . import adipiscing.lorem_ipsum 是一个语法错误。

不满足的选项

使用隐式相对导入

# consecteur.py

import adipiscing.lorem_ipsum

dolor = adipiscing.lorem_ipsum.dolor_sit_amet()

这不必要地混淆了adipiscing.lorem_ipsum 是绝对导入还是相对导入。当导入是相对的时,代码应该是显式的。

将模块从其命名空间包中拉出

# consecteur.py

from .adipiscing import lorem_ipsum

dolor = lorem_ipsum.dolor_sit_amet()

这会丢失通过阅读 adipiscing.lorem_ipsum 传达的有价值的信息,尤其是如果 lorem_ipsum 是一个通用词,需要adipiscing 包命名空间上下文化。

使用错误名称导入

# consecteur.py

from .adipiscing import lorem_ipsum as adipiscing_lorem_ipsum

dolor = adipiscing_lorem_ipsum.dolor_sit_amet()

这在视觉上令人困惑;期待adipiscing.lorem_ipsum 的人可以轻松输入期待它工作的人,但该名称不可用。取一个容易混淆的名字并不是一个好的解决方案;两者都不是一个独特的名称,因为整个目的是使adipiscing.lorem_ipsum可用。

如果包或模块名称中的一个或两个实际上已经有下划线,这也是模棱两可的。如果下划线代表一个点,则它与实际包含下划线的名称无法区分。

导入包,尝试使用模块

# consecteur.py

from . import adipiscing

dolor = adipiscing.lorem_ipsum.dolor_sit_amet()

这是一个 AttributeError,因为 adipiscing.lorem_ipsum 现在不可用;仅通过导入包含的包,模块不会自动可用。

导入包,然后导入模块,但不要使用它的名字

# consecteur.py

from . import adipiscing
from .adipiscing import lorem_ipsum

dolor = adipiscing.lorem_ipsum.dolor_sit_amet()

这个 hack 成功了,但是 import 语句 from .adipiscing import lorem_ipsum 声明我们将使用纯 lorem_ipsum 名称。

由于这不是真的,静态代码检查器会(正确地)抱怨未使用的导入。我同意那些代码检查器,所以我不只是想消除警告;我想避免黑客攻击,并且仍然可以使用 adipiscing.lorem_ipsum 名称。

那么,我怎样才能使adipiscing.lorem_ipsum 名称可用于代码通过该名称,使用显式相对导入没有未使用的导入强>?

【问题讨论】:

  • 如果您担心代码检查器(即 flake8),只需将 # noqa: F401 附加到行并注释您这样做的原因。
  • 或者只使用完整的导入,因为这样可以完全消除事物的歧义并且更加明确。
  • 或者,尝试在from . import adipiscing之后查看,只需执行from adipiscing import lorem_ipsum,注意adipiscing缺少前导.

标签: python namespaces python-import


【解决方案1】:

Python 的解释器不支持您想要的语法。但是您可以使用as 作为“将模块从其命名空间包中拉出” 的解决方法。例如:

from .lorem import ipsum as lorem_ipsum

dolor = lorem_ipsum.dolor_sit_amet()

这样做你会得到完整的上下文,它是lorem's ipsum

【讨论】:

  • 谢谢。我已经更新了问题以说明为什么这还不够。
【解决方案2】:

目前似乎没有办法使用 Python 导入系统来做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2021-02-08
    • 2018-08-05
    • 2020-04-09
    • 2019-11-22
    相关资源
    最近更新 更多