例如,在multiprocessing
包中,我们可以使用Process
导入类from multiprocessing import Process
。为什么不from multiprocessing.context import Process
它真正属于哪里?
事实上,我发现它们是一样的。为什么呢?
答案 0 :(得分:2)
通常会将导入添加到__init__
以缩短导入路径并定义公共接口。 multiprocessing.context import Process
是一个内部接口,将来可以更改而不保持任何向后兼容性。
另一方面,multiprocessing import Process
是文档化的公共接口,不会更改为向后兼容性。
您可以看到__all__
under context.py
为空,这意味着它没有公共界面,您不应该在应用程序中从中导入,因为它可以在将来发生变化而不会发出任何警告。
__all__ = [] # things are copied from here to __init__.py
PEP-008的相关章节:
任何向后兼容性保证仅适用于公共接口。因此,重要的是用户能够清楚 区分公共和内部接口。
记录的界面被视为公共界面,除非文档明确声明它们是临时的或内部的 接口免于通常的向后兼容性保证。 应假定所有未记录的接口都是内部接口。
为了更好地支持内省,模块应使用
__all__
属性在其公共API中明确声明名称。设置__all__
到空列表表示该模块没有公共API。即使设置了
__all__
,内部接口(包,模块,类,函数,属性或其他名称)也是如此 应该仍然以单个前导下划线为前缀。如果任何包含名称空间(包,模块或类)的内容被视为内部接口,则接口也被视为内部接口。
导入的名称应始终被视为实施细节。其他模块不得依赖于间接访问 导入的名称,除非它们是明确记录的部分 包含模块的API,例如os.path或包的
__init__
从子模块公开功能的模块。
我认为着名的requests
库有一个非常好的公共界面,你可以看到它是通过导入__init__.py
文件中的大部分内容来完成的。而且你会发现它也是根据__init__.py
文件下的导入进行记录的。
答案 1 :(得分:1)
from multiprocessing import Process
有效,因为Process
已导入__init__.py
包的multiprocessing
。例如,在shell中,键入以下代码:
import multiprocessing
with open(multiprocessing.__file__, 'r') as f:
print(f.readlines())
你会看到以下几行:
from . import context
#
# Copy stuff from default context
#
globals().update((name, getattr(context._default_context, name))
for name in context._default_context.__all__)
__all__ = context._default_context.__all__
所以是的,这是一回事。