没有__init__.py,但仍被视为包裹?

时间:2015-08-29 07:36:50

标签: packages python-3.4 python-import

A foobar package

  
      
  • foobar的

         
        
    • __ init__.py
    •   
    • foo.py
    •   
    •      
          
      • bar.py
      •   
    •   
  •   

Inside the __init__.py

from . import foo
from . import bar

即使bar不是包或子包,它仍然作为模块(lolwut)导入。我在print(type(bar))内执行__init__.py检查了导入类型,并打印了<class 'module'> ......就是这样。这里发生了什么?它是一个模块对象,所以我做print(dir(bar)),输出为['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']。现在,对我来说更令人困惑的是__path__变量。这不是一个只包装的东西吗?

这就是所谓的命名空间包吗?我认为它不是,但我在__init__.py文件中再试了一次 - 添加了一行import bar.bar。它以ImportError结尾。那么,总结一下我的问题,这个模块有用的是什么?为什么Python首先导入这个?

There's an amazing tutorial on this entire topic by David Beazley。我刚才看过整件事,但我想我应该再看一遍回忆一切。

1 个答案:

答案 0 :(得分:0)

来自the docs

  

模块是包含Python定义和语句的文件。文件名是附加后缀.py的模块名称。在模块中,模块的名称(作为字符串)可用作全局变量__name__的值。

     

...

     

包是一种使用“点模块名称”构建Python模块命名空间的方法。例如,模块名称A.B在名为A。

的包中指定名为B的子模块      

...

     

Packages支持另一个特殊属性__path__。这被初始化为一个列表,其中包含在执行该文件中的代码之前保存包__init__.py的目录的名称。这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。

     

虽然通常不需要此功能,但可用于扩展程序包中的模块集

所以是的,__path__变量也应用于包内的模块,这些模块被视为包的子模块&#39;

修改的 在Python 2.x中,包含from . import bar的包将在该行返回ImportError。在Python 3.x上,modulefoobar.foo的{​​{1}}类型和<module 'foobar.foo' from '../py/foobar/foo.py'>的{​​{1}}类型。

显然,它出现了here

  

常规包将继续具有init.py并将驻留在单个目录中。命名空间包不能包含init.py