为什么包在__init__.py文件下有导入?

时间:2017-08-06 00:47:00

标签: python import packages python-import

例如,在multiprocessing包中,我们可以使用Process导入类from multiprocessing import Process。为什么不from multiprocessing.context import Process它真正属于哪里?

事实上,我发现它们是一样的。为什么呢?

2 个答案:

答案 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的相关章节:

Public and internal interfaces

  

任何向后兼容性保证仅适用于公共接口。因此,重要的是用户能够清楚   区分公共和内部接口。

     

记录的界面被视为公共界面,除非文档明确声明它们是临时的或内部的   接口免于通常的向后兼容性保证。   应假定所有未记录的接口都是内部接口。

     

为了更好地支持内省,模块应使用__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__

所以是的,这是一回事。