关于包:Python模块的绝对与显式相对导入

Absolute vs. explicit relative import of Python module

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

1
2
3
project.app1.models
project.app1.views
project.app2.models

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

绝对进口:

1
2
import A.A
import A.B.B

或者使用显式的相对导入,如python 2.5中使用pep 328引入的那样:

1
2
3
# explicit relative
import ..A
import .B

做这件事最要紧的方法是什么?


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

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

"Isn't this mostly historical? Until the new relative-import syntax
was implemented there were various problems with relative imports. The
short-term solution was to recommend not using them. The long-term
solution was to implement an unambiguous syntax. Now it is time to
withdraw the anti-recommendation. Of course, without going overboard
-- I still find them an acquired taste; but they have their place."

OP正确链接了PEP 328,该PEP 328表示:

Several use cases were presented, the most important of which is being
able to rearrange the structure of large packages without having to
edit sub-packages. In addition, a module inside a package can't easily
import itself without relative imports.

另请参见几乎重复的问题:何时或为何在python中使用相对导入

当然,它仍然是一个品味问题。虽然使用相对导入来移动代码比较容易,但这也可能会意外地破坏某些内容;重命名导入并不那么困难。

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

1
from __future__ import absolute_import

在这种情况下,隐式相对导入将不再可能(例如,import localfile将不再起作用,只有from . import localfile起作用)。对于清洁和未来的行为,建议使用绝对进口。

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

在评估最佳方法时,应考虑到这一限制。在任何情况下,guido都反对从模块运行脚本:

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.

关于这件事的详尽讨论可以在SO;RE上找到。python 3非常全面:

  • python 3中的相对导入


绝对进口。来自PEP 8:

Relative imports for intra-package imports are highly
discouraged.
Always use the absolute package path for all imports.
Even now that PEP 328 [7] is fully implemented in Python 2.5,
its style of explicit relative imports is actively discouraged;
absolute imports are more portable and usually more readable.

显式相对导入是一种很好的语言特性(我猜),但它们并没有绝对导入那么明确。更易读的形式是:

1
2
import A.A
import A.B.B

尤其是导入几个不同的名称空间时。如果您看到一些编写良好的项目/教程,其中包括从包中导入的内容,那么它们通常遵循这种风格。

当其他人(也许是你)试图找出你的名称空间时(尤其是当你迁移到3.x时,其中一些包名称已经更改),你需要的一些额外的击键更加明确,这将在将来为他们节省大量的时间。


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