如何编写好的/correct __init__.py 文件

245 投票
3 回答
211393 浏览
提问于 2025-04-15 17:16

我的包的结构如下:

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
   ...

我不太确定 __init__.py 文件应该怎么写才算正确。
__init__.py #1 看起来是这样的:

__all__ = ['mapper', 'vehicle']
import mapper
import vehicle

那么,比如说 __init__.py #2 应该是什么样子的呢?我的内容是:

__all__ = ['basemapper', 'lxml']
from basemaper import *
import lxml

什么时候应该使用 __all__ 呢?

3 个回答

6

你的 __init__.py 文件里应该有一个 文档字符串

虽然所有的功能都是在模块和子包中实现的,但你的包的文档字符串是用来说明从哪里开始的地方。例如,可以看看这个 python 的 email。这个包的文档就像是一个介绍,讲述了它的目的、背景,以及包内各个组件是如何协同工作的。如果你使用 sphinx 或其他工具自动生成文档,包的文档字符串正是描述这种介绍的最佳位置。

关于其他内容,可以参考 firecrowAlex Martelli 的精彩回答。

126

我自己的 __init__.py 文件大多数时候都是空的。特别是,我从来不会在 __init__.py 里写 from blah import * 这种语句。如果“导入这个包”意味着获取包里直接定义的各种类、函数等,那我宁愿把 blah.py 的内容直接复制到包的 __init__.py 里,然后把 blah.py 删除掉(增加源文件没有什么好处)。

如果你真的想支持 import * 这种写法(哎呀),那么使用 __all__(尽量让这个列表里的名字少一些)可能会对控制损害有所帮助。一般来说,命名空间和明确的导入是的东西,我强烈建议你重新考虑任何系统性绕过这两个概念的方法!-)

186

__all__ 是个很好的东西 - 它可以帮助我们管理导入的模块,而不是自动导入所有模块。http://docs.python.org/tutorial/modules.html#importing-from-a-package

使用 __all__import * 是多余的,只需要 __all__ 就可以了。

我认为在 __init__.py 文件中使用 import * 来导入包的一个强大理由是,它可以让我们在不破坏现有应用的情况下,重构一个已经变成多个脚本的脚本。不过,如果你是从头开始设计一个包,最好把 __init__.py 文件留空。

例如:

foo.py - contains classes related to foo such as fooFactory, tallFoo, shortFoo

然后应用程序发展壮大,现在变成了一个完整的文件夹。

foo/
    __init__.py
    foofactories.py
    tallFoos.py
    shortfoos.py
    mediumfoos.py
    santaslittlehelperfoo.py
    superawsomefoo.py
    anotherfoo.py

这时,初始化脚本可以这样写:

__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

这样,写好的脚本在变更时不会出错:

from foo import fooFactory, tallFoo, shortFoo

撰写回答