复杂包结构中的Python import语句?

时间:2015-05-14 14:06:55

标签: python import

考虑以下三个常规包及其类别的层次结构 内容:

quick
├── brown
│   ├── fox.py
│   └── __init__.py
├── lazy
│   ├── dog.py
│   └── __init__.py
└── __init__.py

现在假设模块jump中有一个函数dog,模块fox中需要它。我该怎么办?

最近见过Raymond Hettinger的talk at Pycon 2015我想要的 可以从包lazy的根目录直接导入的函数, 像这样:

from lazy import jump 

另外,在我看来,编写相对导入更简洁 使包内连接容易可见。因此,我会写 这进入lazy/__init__.py

from .dog import jump

这是fox.py

from ..lazy import jump

但我想知道,这是正确的方法吗?

首先,在jump中导入名称lazy/__init__.py无效 防止它直接从dog导入。如果某个功能可能从很多地方导入,会导致问题吗?例如,在单元测试中,我们是否可能从错误的位置修改名称?

此外,具有自动导入例程的IDE似乎更喜欢从定义函数的模块导入。我可以通过将字符_放在所有模块名称前面来覆盖它,但这似乎有点不切实际。

将所有需要的名字带到外面是否危险 打包到__init__.py?可能这至少会增加 循环进口的可能性。但我想如果是圆形的话 遇到导入存在根本性的错误 包装结构无论如何。

相对进口情况如何? PEP 8说 建议绝对进口:当它说绝对时意味着什么 进口表现比相对表现好吗?你能给我一个 示例

1 个答案:

答案 0 :(得分:3)

显式接口声明:如果您希望将jump函数公开为属于lazy包,那么将它包含在lazy.__init__中是有意义的,正如你的建议。这样你就可以清楚地知道它是lazy的“公共接口”的一部分。您还建议其他模块不属于公共接口。

防止人/工具直接从dog 导入:在Python中,隐私取决于用户的同意,您不能强行隐藏任何内容,但有约定。

使用下划线并定义dog._jump()可明确dog 想要公开_jump。我们可以假设任何IDE工具都应该遵守这种类型的约定。无论如何,如果dog定义_jumplazy公开jump,那么您就不会有不知道哪些是导入的问题,因为名称不同,所以这是明确的,在Python中被认为是好的。

这是关于这个主题的一个很好的指针:Defining private module functions in python

关于相对进口::PEP 8不鼓励这些,但是出于某种原因实施了它们,它们取代了隐含的相对进口。 PEP 8中的原因:尤其是在处理使用绝对导入的复杂包布局时,会有不必要的冗长

最后的想法:简而言之,如果您认为lazy包是一个库并且不想公开内部模块,那么我认为暴露它是有意义的lazy.__init__中的对象。如果相反,你希望人们知道有一个dog模块,那么无论如何,让其他模块做:

from lazy.dog import jump

from ..lazy import jump

如果brownbrown.fox将始终打包并与lazy紧密集成,那么我看不出绝对和相对之间的区别,但我会稍微偏爱相对,明确表示您指的是内部模块。

但如果你认为他们将来会被拆分,那么相对导入没有意义,而你宁可这样做,具体取决于以上几点:

from lazy.dog import jump
或:
from lazy import jump