如何编写正确/正确的包__init__.py文件

Mar*_*uer 179 python packages

我的包具有以下结构:

mobilescouter/
    __init__.py #1
    mapper/
        __init__.py  #2
        lxml/
            __init__.py #3
            vehiclemapper.py
            vehiclefeaturemapper.py
            vehiclefeaturesetmapper.py
        ...
        basemapper.py
   vehicle/
        __init__.py #4
        vehicle.py
        vehiclefeature.py
        vehiclefeaturemapper.py
   ...
Run Code Online (Sandbox Code Playgroud)

我不确定__init__.py文件应该如何正确编写.
__init__.py #1样子:

__all__ = ['mapper', 'vehicle']
import mapper
import vehicle
Run Code Online (Sandbox Code Playgroud)

但是应该__init__.py #2怎么样?我的是:

__all__ = ['basemapper', 'lxml']
from basemaper import *
import lxml
Run Code Online (Sandbox Code Playgroud)

什么时候应该__all__使用?

Fir*_*row 141

__all__非常好 - 它有助于指导import语句而无需自动导入模块 http://docs.python.org/tutorial/modules.html#importing-from-a-package

使用__all__import *冗余,只__all__需要

我认为import *__init__.py导入包中使用的最有力的原因之一是能够重构已经发展成多个脚本而不破坏现有应用程序的脚本.但是,如果你从一开始就设计一个包.我认为最好把__init__.py文件留空.

例如:

foo.py - contains classes related to foo such as fooFactory, tallFoo, shortFoo
Run Code Online (Sandbox Code Playgroud)

然后应用程序增长,现在它是一个完整的文件夹

foo/
    __init__.py
    foofactories.py
    tallFoos.py
    shortfoos.py
    mediumfoos.py
    santaslittlehelperfoo.py
    superawsomefoo.py
    anotherfoo.py
Run Code Online (Sandbox Code Playgroud)

那么init脚本可以说

__all__ = ['foofactories', 'tallFoos', 'shortfoos', 'medumfoos',
           'santaslittlehelperfoo', 'superawsomefoo', 'anotherfoo']
# deprecated to keep older scripts who import this from breaking
from foo.foofactories import fooFactory
from foo.tallfoos import tallFoo
from foo.shortfoos import shortFoo
Run Code Online (Sandbox Code Playgroud)

以便在更改期间写入以执行以下操作的脚本不会中断:

from foo import fooFactory, tallFoo, shortFoo
Run Code Online (Sandbox Code Playgroud)

  • 我对'__all__'和逐行导入感到非常困惑.你的榜样很有启发性. (3认同)
  • 我对“`__all__`和`import *`是多余的”感到困惑,`__all__`由模块的使用者使用,而`from foo import *`由模块本身使用以使用其他模块。... (2认同)

Ale*_*lli 109

我自己的__init__.py文件经常是空的.特别是,我从来没有from blah import *作为一部分__init__.py- 如果"导入包"意味着获得所有类,函数等直接定义为包的一部分,那么我将词汇复制blah.py到包的内容__init__.py而不是删除blah.py(源文件的乘法在这里没有好处).

如果你坚持支持import *成语(eek),那么使用__all__(尽可能微小的名字列表,你可以带来它)可能有助于控制伤害.一般来说,命名空间和显式导入是好事,我强烈建议重新考虑基于系统地绕过其中一个或两个概念的任何方法! - )

  • 就个人而言,我更喜欢将事物分开,然后导入*.原因是,尽管折叠和东西,我仍然讨厌浏览包含太多类的文件,即使相关. (9认同)
  • @sunqiang这是个人的,但我不这么认为.`from mobilescouter import A,B`只是一行代码,你没有一个包含666个类的项目,每个项目都有自己的文件,对吧?如果你的代码中有两个或更多的`import*`,你就会在命名空间中填充潜在的垃圾,很快就会忘记`A`的来源.如果上层包装也这样做?你正在抓住所有的子包和子包.就像python的禅宗所说,显性比隐含更好. (5认同)
  • @stefano想到一个大框架.如果它使用`import*`,你必须无条件地接受所有框架中的所有框架,甚至是你永远不会使用的功能.保持`__init __.py`为你提供更多的机会,而不仅仅是全有或全无的语义.想想扭曲. (4认同)
  • @mg,如果 __init__.py 文件中有一行“import A, B”,那么我可以使用以下语法调用 A(或 B):mobilescouter.A; 如果我们使用“from mobilescouter import A, B”,那么它只是 A.something。有时只是这一行,我不记得 A 是 mobilescouter 的子包,我认为这会导致名称空间污染(尽管它比“”from mobilescouter import *”好很多。我仍然更喜欢“import pkgname”给用户统一的公共接口。所以 __init__.py 做 import sub_pkgname 的事情。 (2认同)

ger*_*rit 6

__init__.py应该有一个文档字符串

尽管所有功能都是在模块和子包中实现的,但包文档字符串是记录从哪里开始的地方。例如,考虑pythonemail。包文档是描述目的、背景以及包中的各个组件如何协同工作的简介。如果您使用 sphinx 或其他包自动从文档字符串生成文档,则包文档字符串正是描述此类介绍的正确位置。

对于任何其他内容,请参阅firecrowAlex Martelli的精彩回答。