99

我想知道在 Python 应用程序中导入包的首选方式。我有一个这样的包结构:

project.app1.models
project.app1.views
project.app2.models

project.app1.views进口project.app1.modelsproject.app2.models. 有两种方法可以做到这一点。

绝对进口:

import A.A
import A.B.B

或者使用显式的相对导入,如Python 2.5 和 PEP 328中介绍的那样:

# explicit relative
from .. import A
from . import B

最pythonic的方法是什么?

4

3 回答 3

137

不再强烈建议使用 Python 相对导入,但强烈建议在这种情况下使用 absolute_import。

请参阅引用 Guido 本人的讨论:

“这不是历史性的吗?在实施新的相对导入语法之前,相对导入存在各种问题。短期解决方案是建议不要使用它们。长期解决方案是实施明确的语法。现在“是时候撤回反推荐了。当然,不要过分——我仍然认为它们是后天习得的;但它们有它们的位置。”

OP 正确链接了PEP 328,上面写着:

介绍了几个用例,其中最重要的是能够重新排列大包的结构而无需编辑子包。此外,包内的模块在没有相对导入的情况下无法轻松导入自身。

另请参阅几乎重复的问题何时或为什么在 Python 中使用相对导入

当然,它仍然是一个品味问题。虽然使用相对导入来移动代码更容易,但这也可能会意外地破坏事情;并且重命名导入并不难。

要强制 PEP 328 中的新行为,请使用:

from __future__ import absolute_import

在这种情况下,隐式相对导入将不再可能(例如,import localfile将不再起作用,仅from . import localfile)。对于干净且面向未来的行为,建议使用 absolute_import。

一个重要的警告是,由于 PEP 338PEP 366,相对导入需要将 python 文件作为模块导入 - 你不能执行具有相对导入的 file.py ,否则你会得到一个ValueError: Attempted relative import in non-package.

This limitation should be taken into account when evaluating the best approach. Guido is against running scripts from a module in any case:

I'm -1 on this and on any other proposed twiddlings of the __main__ machinery. The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern. To make me change my mind you'd have to convince me that it isn't.

Exhaustive discussions on the matter can be found on SO; re. Python 3 this is quite comprehensive:

于 2013-05-25T09:54:02.490 回答
63

绝对进口。从 PEP 8:

非常不鼓励用于包内导入的相对导入。始终对所有导入使用绝对包路径。即使现在 PEP 328 [7] 已在 Python 2.5 中完全实现,它的显式相对导入风格也被积极劝阻。绝对导入更便携,通常更具可读性。

显式相对导入是一个不错的语言功能(我猜),但它们并不像绝对导入那样显式。更易读的形式是:

import A.A
import A.B.B

特别是如果您导入几个不同的命名空间。如果您查看一些包含从包中导入的编写良好的项目/教程,它们通常遵循这种风格。

当他们试图找出你的命名空间时(特别是如果你迁移到 3.x,其中一些包名称已更改)。

于 2010-11-17T22:22:48.073 回答
41

相对导入不仅让您以后可以在不更改数十个内部导入的情况下自由重命名包,而且我还成功地解决了涉及循环导入或命名空间包等某些问题,因为它们不会将“Python”发送回top" 以从顶级命名空间重新开始搜索下一个模块。

于 2010-11-17T22:25:57.380 回答