Python3.3中的包是否不需要_init__u;.py+

我正在使用Python 3.5.1。我在这里阅读了文件和文件包部分:https://docs.python.org/3/tutorial/modules.html#packages

现在,我有以下结构:

/home/wujek/playerd/a/b/module.py

module.py

类Foo:
定义初始化(自):
打印('初始化Foo')

现在,在/home/wujek/playdey

~/playerd$python3
&燃气轮机&燃气轮机&燃气轮机;导入a.b.模块
&燃气轮机&燃气轮机&燃气轮机;a、 b.module.Foo()
初始化Foo
<a、 0x100a8f0b8处的b.module.Foo对象>

同样,现在在家里,操场的超级玩家

~$PYTHONPATH=游乐场蟒蛇3
&燃气轮机&燃气轮机&燃气轮机;导入a.b.模块
&燃气轮机&燃气轮机&燃气轮机;a、 b.module.Foo()
初始化Foo
<a、 0x10a5fee10处的b.module.Foo对象>

事实上,我可以做各种各样的事情:

~$PYTHONPATH=游乐场蟒蛇3
&燃气轮机&燃气轮机&燃气轮机;导入
&燃气轮机&燃气轮机&燃气轮机;进口a.b
&燃气轮机&燃气轮机&燃气轮机;进口游乐场

为什么这样做有效?我认为当Python路径指向游乐场文件夹时,ab中都需要有\uuu init\uuuuuuuuuuuupy文件(空的文件可以工作)

这似乎与Python 2.7有所不同:

~$PYTHONPATH=python
&燃气轮机&燃气轮机&燃气轮机;导入
ImportError:没有名为的模块
&燃气轮机&燃气轮机&燃气轮机;进口a.b
ImportError:没有名为a.b的模块
&燃气轮机&燃气轮机&燃气轮机;导入a.b.模块
ImportError:没有名为a.b.module的模块

~/playway/a~/playway/a/b中使用.\uuu init\uuu.py,工作正常

概述

@迈克的回答是正确的,但太不准确了。确实,Python 3.3+支持隐式名称空间包,允许它在不使用\uuuu init\uuuuuuuuuu.py文件的情况下创建包。这被称为名称空间包,与常规包不同,后者确实有一个\uuuu init\uuuuuuuuuy.py文件(空或不空)

但是,只有在需要时才能创建名称空间包。对于大多数用例和开发人员来说,这并不适用,因此不管怎样,您都应该坚持使用\uuuu init\uuuu.py文件

命名空间包用例

为了演示这两种python包之间的差异,让我们看一下以下示例:

google\u pubsub/<-包1
谷歌/<-名称空间包(没有_uinit__uu.py)
云/<-名称空间包(没有_uinit__uu.py)
pubsub/<-常规软件包(带有_uinit__uu.py)
__初始值py<-需要使包装成为常规包装
福比
google_storage/<-方案2
谷歌/<-名称空间包(没有_uinit__uu.py)
云/<-名称空间包(没有_uinit__uu.py)
存储/<-常规软件包(带有_uinit__uu.py)
__初始值py<-需要使包装成为常规包装
巴比

google\u pubsubgoogle\u storage是独立的软件包,但它们共享相同的命名空间google/cloud。为了共享同一名称空间,需要将公共路径的每个目录设置为名称空间包,即google/cloud/这应该是创建名称空间包的唯一用例,否则就没有必要了。

googlegoogle/cloud目录中没有\uuuu init\uuuu py文件非常重要,这样这两个目录都可以解释为命名空间包。在Python3.3+中,sys.path上任何名称与正在查找的包名称匹配的目录都将被识别为该包的贡献模块和子包。因此,当您同时从google_pubsubgoogle_storage导入时,Python解释器将能够找到它们

这与常规包不同,常规包是自包含的,这意味着所有部分都位于同一目录层次结构中。当导入包时,Python解释器在sys.path上遇到带有\uuuu init\uuuuu.py文件的子目录时,它将创建一个仅包含该目录中模块的目录包,而不是在该目录外找到所有适当命名的子目录这对于不想共享名称空间的包来说非常好。我强烈建议大家看看Python导入系统中的陷阱,以便更好地了解Python导入在常规和命名空间包中的行为,以及需要注意的\uuuuu init\uuuuuuuuupy陷阱

总结

  • 如果要创建命名空间包,请仅跳过\uuuuu init\uuuuuuuuuuuuupy.py文件。仅当您有位于不同位置的不同库,并且希望它们各自为父包(即命名空间包)贡献一个子包时,才创建命名空间包
  • 继续将空的\uuuu init\uuuu py添加到您的目录中,因为99%的时间您只想创建常规包。此外,Python工具,如mypypytest需要空的\uuuu init\uuuuuuuupy.py文件来相应地解释代码结构。如果不小心,这可能会导致奇怪的错误

资源

我的回答只触及了常规包名称空间包的工作原理,因此请查看以下参考资料以获取更多信息:

  • PEP 420——隐式命名空间包
  • 进口系统-常规包装
  • 导入系统命名空间包
  • Python导入系统中的粗心陷阱

发表评论