0

我有一个包含几个包含__init__.py文件的子目录的包。这些文件执行检查和初始化作业。

现在我在其中一些文件夹中还有一个不应该被 an 直接引用的文件,import因为它依赖于在其各自的__init__.py. 让我们将这些称为“隐藏模块”——作为惯例,我使用下划线使它们变得明显。

在我的__init__.py_implementation.py位于同一文件夹中)中执行以下操作是否是一个坏主意:

import os, sys
if sanity_check_successful:
    from ._implementation import *
    __all__ = sys.modules[__name__ + "._implementation"].__all__

这个想法应该很清楚,每当完整性检查失败时,我都会尝试在包中的每个相应模块级别提供有意义的错误信息。

这是一个坏主意,即__all__从“隐藏模块”复制数组吗?如果是这样,为什么以及是否有更好的选择?

加分点:有没有更简洁的方式来写这两行?:

    from ._implementation import *
    __all__ = sys.modules[__name__ + "._implementation"].__all__

特别是让我很恼火的是,我必须在一个地方使用一个字符串"._implementation"并在另一个地方使用一个模块名称。

4

2 回答 2

3

__all__从子模块有更简单的设置方法._implementation;否则设置__all__很好:

from ._implementation import *
from ._implementation import __all__

这只是将其导入__all__并绑定到本地模块命名空间__all__

于 2013-06-05T21:39:19.377 回答
1

甚至比 Martijn Pieters 的回答更简单:

如果您包含'__all__'__all__列表中._implementation,它将由您的单行自动导入from ._implementation import *


至于你的主要问题,这是否是一个坏主意……</p>

嗯,这取决于你在做什么。这基本上使您的包看起来完全像它的_implementation模块。如果这就是你所做的一切,那很好......但在那种情况下,为什么不首先搬进_implementation去呢__init__

如果您尝试将多个模块合并为一个,您可能希望它们的所有__all__列表添加到一个中。stdlib 有这样的例子,比如collections,通常的模式是:

from collections.abc import *
import collections.abc
__all__ += collections.abc.__all__

这可能看起来有点冗长,但肯定很清楚。


从您编辑的问题中,我认为您所做的事情以完全相同的方式是合理的collections,最清晰和最惯用的解决方案是做同样的事情,但使用=而不是+=(因为您只是复制一个列表而不是将多个列表添加在一起)。

但是,既然这样:

import foo
bar = foo.bar

......几乎等同于(对于您的用例而言足够接近):

from foo import bar

… Martijn Pieters 的回答很简单:

from ._implementation import *
from ._implementation import __all__

所以,我会这样做。

于 2013-06-05T21:44:51.850 回答