Python模块的绝对导入与显式相对导入
我在想在Python应用程序中导入包的最佳方式是什么。我有这样的包结构:
project.app1.models
project.app1.views
project.app2.models
project.app1.views
导入了 project.app1.models
和 project.app2.models
。我想到两种方法来实现这一点。
第一种是使用绝对导入:
import A.A
import A.B.B
第二种是使用显式的相对导入,这种方式是在 Python 2.5中引入的PEP 328:
# explicit relative
from .. import A
from . import B
那么,最符合Python风格的做法是什么呢?
3 个回答
相对导入的好处在于,你可以随意重命名你的包,而不需要去修改很多内部的导入语句。此外,我也发现它们在解决一些问题时很有效,比如循环导入或者命名空间包的问题,因为使用相对导入时,Python不会“回到最上面”重新开始查找下一个模块,这样可以避免一些麻烦。
在Python中,相对导入现在不再被强烈反对,但在这种情况下,强烈建议使用绝对导入。
请查看这个讨论,里面提到了Guido本人:
“这不是主要是历史原因吗?在新的相对导入语法实施之前,相对导入存在各种问题。短期解决方案是建议不要使用它们。长期解决方案是实现一种明确的语法。现在是时候撤回反对的建议了。当然,不要过于极端——我仍然觉得它们需要适应;但它们确实有其用处。”
原作者正确地链接了PEP 328,其中提到:
提出了几种使用案例,其中最重要的是能够在不编辑子包的情况下重新安排大型包的结构。此外,包内的模块如果没有相对导入,无法轻松导入自身。
还可以查看几乎重复的问题在Python中何时或为什么使用相对导入
当然,这仍然是个人喜好的问题。虽然使用相对导入可以更方便地移动代码,但这也可能意外地导致问题;而且重命名导入并不难。
要强制使用PEP 328的新行为,可以使用:
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在任何情况下都反对从模块运行脚本:
我对这个以及其他任何对__main__机制的修改持反对态度。唯一的使用案例似乎是运行恰好位于模块目录中的脚本,而我一直认为这是反模式。要让我改变主意,你必须说服我这不是反模式。”
关于这个问题的详细讨论可以在SO上找到;关于Python 3的讨论相当全面:
绝对导入。从PEP 8的规定来看:
对于包内的相对导入,强烈不推荐使用。所有的导入都应该使用绝对包路径。即使现在PEP 328已经在Python 2.5中完全实现,使用显式的相对导入也不被鼓励;绝对导入更具可移植性,通常也更易读。
显式的相对导入是一个不错的语言特性(我想),但它们并没有绝对导入那么明确。更易读的写法是:
import A.A
import A.B.B
特别是当你导入多个不同的命名空间时。如果你看看一些写得好的项目或教程,它们通常会遵循这种风格。
你多敲几下键盘来让导入更明确,将来会为其他人(也可能是你自己)节省很多时间,特别是在他们试图理解你的命名空间时(尤其是当你迁移到3.x版本时,一些包的名称已经改变)。