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

问题:如何编写良好/正确的__init__.py包文件

我的软件包具有以下结构:

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__使用?

My package has the following structure:

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

I’m not sure how the __init__.py files should be correctly written.
The __init__.py #1 looks like:

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

But how should for example __init__.py #2 look like? Mine is:

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

When should be __all__ used?


回答 0

__all__很好-它有助于指导导入语句,而无需自动导入模块 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

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

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

__all__ is very good – it helps guide import statements without automatically importing modules http://docs.python.org/tutorial/modules.html#importing-from-a-package

using __all__ and import * is redundant, only __all__ is needed

I think one of the most powerful reasons to use import * in an __init__.py to import packages is to be able to refactor a script that has grown into multiple scripts without breaking an existing application. But if you’re designing a package from the start. I think it’s best to leave __init__.py files empty.

for example:

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

then the app grows and now it’s a whole folder

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

then the init script can say

__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

so that a script written to do the following does not break during the change:

from foo import fooFactory, tallFoo, shortFoo

回答 1

我自己的__init__.py文件经常为空。特别是,我从来没有加入from blah import *__init__.py-如果“导入包”意味着直接将各种类,函数等定义为包的一部分,那么我将以词法将其内容复制blah.py到包的内容中__init__.py并删除blah.py(源文件的乘法在这里没有好处)。

如果您确实坚持支持import *惯用语(eek),那么使用__all__(尽量减少使用姓名列表)可能会有助于控制损失。通常,命名空间和显式导入是一件好事,我强烈建议您重新考虑基于系统地绕过一个或两个概念的任何方法!

My own __init__.py files are empty more often than not. In particular, I never have a from blah import * as part of __init__.py — if “importing the package” means getting all sort of classes, functions etc defined directly as part of the package, then I would lexically copy the contents of blah.py into the package’s __init__.py instead and remove blah.py (the multiplication of source files does no good here).

If you do insist on supporting the import * idioms (eek), then using __all__ (with as miniscule a list of names as you can bring yourself to have in it) may help for damage control. In general, namespaces and explicit imports are good things, and I strong suggest reconsidering any approach based on systematically bypassing either or both concepts!-)


回答 2

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

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

有关其他任何内容,请参阅firecrowAlex Martelli的出色回答。

Your __init__.py should have a docstring.

Although all the functionality is implemented in modules and subpackages, your package docstring is the place to document where to start. For example, consider the python email package. The package documentation is an introduction describing the purpose, background, and how the various components within the package work together. If you automatically generate documentation from docstrings using sphinx or another package, the package docstring is exactly the right place to describe such an introduction.

For any other content, see the excellent answers by firecrow and Alex Martelli.