我最近升级了流行的Python样式检查器pylint的版本。
在我的代码中它一直是弹道的,指出了我在同一软件包中导入模块的位置,而没有指定完整的软件包路径。
新错误消息是W0403。

W0403:相对导入%r,应为%r
当检测到相对于软件包目录的导入时使用。


示例
例如,如果我的包装结构如下:
/cake
  /__init__.py
  /icing.py
  /sponge.py
/drink

,然后在海绵包装中写:
import icing
import cake.icing

我会收到此错误。

虽然我知道并非所有的Pylint消息都具有同等的重要性,而且我不惧怕将其消除,但我不明白为什么会这样实践被认为是一个糟糕的主意。
我希望有人可以解释这些陷阱,因此我可以改善自己的编码风格,而不是(按照我目前的计划)关闭此表面上虚假的警告。

#1 楼

import icing的问题是您不知道它是绝对导入还是相对导入。 icing可以是python路径中的模块,也可以是当前模块中的软件包。当本地包的名称与python标准库包的名称相同时,这很烦人。

您可以执行from __future__ import absolute_import来完全关闭隐式相对导入。在PEP 328中对此进行了描述(包括有关歧义的理由)。我相信Python 3000的隐式相对导入已完全关闭。像这样:

from . import icing


评论


+1,特别是针对折衷解决方案,这可能是我应该采取的方式。

–奇怪的思考
2012年8月4日15:46

请注意,您也可以导入.icing而不是from。进口糖衣

–杰克
2015年10月14日,下午1:43

@Jack实际上我认为你不能。从PEP328的这一部分开始:相对导入必须始终使用from <> import; import <>始终是绝对的。当然,绝对导入可以通过省略前导点从<>导入中使用。禁止导入.foo的原因是,导入XXX.YYY.ZZZ之后,表达式中可以使用XXX.YYY.ZZZ。但是.moduleY在表达式中不可用。

–万
2015年11月13日19:50



#2 楼

有几个很好的理由:




当您移动模块时,相对导入很容易中断。包装中的foo.barfoo.baz模块。 baz导入了foo.bar,但是使用了相对导入。

现在,如果要将foo.baz移至foo.bar,则模块突然导入了另一个bar


相对进口是模棱两可的。即使在上面的示例中没有遍历baz模块,也可以原谅进入您的项目的新开发人员,因为他们没有意识到bar实际上是baz而不是根级foo.baz软件包。它明确说明正在使用什么模块。正如baz所讲的那样,显式要比隐式更好。


Python 3完全禁用了隐式相对导入。现在,导入始终被解释为绝对导入,这意味着在上面的示例中,import this将始终导入顶级模块。您将不得不使用显式导入语法(import baz)。

将示例从Python 2移植到3会导致意外的问题,现在使用绝对导入将使您的代码适应未来。 br />


评论


为#2和#3 +1。但是#1必须与整个目录移动时发生的偏移(例如下移一个级别)。

–奇怪的思考
2012年8月4日15:46