良い/正しいパッケージ__init__.pyファイルを書くには


187

私のパッケージの構造は次のとおりです。

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__使用すべきですか?


2
ただし、コードでimport *を使用することは一般的に非常に悪い習慣であり、可能であれば回避する必要があることに注意してください。このための適切な使用例はほとんどありませんが、それらは本当にまれです。
Mayou36 2017

PSA:優れた名前空間パッケージ(新しい種類のパッケージ)を作成する方法に興味がある場合は、このサンプルパッケージを確認してください:github.com/pypa/sample-namespace-packages
Kyle

回答:


145

__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

その後、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

以下を実行するように記述されたスクリプトが変更中に中断しないように:

from foo import fooFactory, tallFoo, shortFoo

3
すべて」と行ごとのインポートについて非常に混乱しました。あなたの例は非常に光っています。
Junchen、2016年

2
「冗長です」__all__と混同され、モジュールのコンシューマーによって使用され、モジュール自体が他のユーザーを使用するために使用されます...import *__all__from foo import *
Nick T

using __all__ and import * is redundant, only __all__ is needed それらはどのように冗長ですか?彼らは異なることをします。
エンドリス

112

自分の__init__.pyファイルが空であることが多いです。特に、私はのfrom blah import *一部を決して持っていません__init__.py-「パッケージのインポート」があらゆる種類のクラス、関数などをパッケージの一部として直接定義することを意味する場合、代わりに内容をblah.pyパッケージのにレキシカルにコピーして__init__.py削除しますblah.py(ソースファイルの乗算はここでは役に立ちません)。

import *イディオム(eek)のサポートを主張する場合は、(最小限__all__の名前のリストを使用して、自分自身をそこに持っていくことができる)を使用すると、損傷の制御に役立ちます。一般に、名前空間と明示的なインポートは良いことであり、どちらかまたは両方の概念を体系的にバイパスすることに基づくアプローチを再検討することを強くお勧めします!-)


9
個人的には、物事を分けてからインポートすることを好みます*。その理由は、折りたたみやその他のことにもかかわらず、たとえ関係があっても、あまりにも多くのクラスを含むファイルを参照することはまだ嫌いだからです。
Stefano Borini、

5
@stefanoは大きなフレームワークについて考えます。それを使用するimport *場合は、すべてのフレームワークを無条件に受け入れる必要があり、使用しない機能も含まれます。__init__.py空のままにしておくと、すべてか何もないセマンティクスよりも多くのチャンスが得られます。ねじれについて考えます。
mg。

空のままにしておくと、mobilescouterをインポートした後でも、mobilescouter.mapper、mobilescouter.vehicle、mobilescouter.whateverを使用できません。mobilescouter.A、mobilescouter.B .....をインポートしすぎませんか?
sunqiang

6
@sunqiangこれは個人的なことですが、私はそうは思いません。from mobilescouter import A, Bほんの1行のコードで、666個のクラスを持つプロジェクトがなく、それぞれに独自のファイルがあるプロジェクトです。import *コードに2つ以上ある場合、名前空間に潜在的なガベージが入り、すぐにAどこから来たかを忘れてしまいます。そして、上位パッケージが同じことをしたら?すべてのサブパッケージとサブサブパッケージを取得しています。Pythonの禅が言うように、明示的は暗黙的よりも優れています。
mg。

1
@ 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はsub_pkgnameのインポートを行います
sunqiang

1

あなたが__init__.py持つべきドキュメンテーション文字列を

すべての機能はモジュールとサブパッケージに実装されていますが、パッケージのdocstringは、どこから開始するかを文書化する場所です。たとえば、python emailパッケージを考えてみましょう。パッケージのドキュメントは、目的、背景、およびパッケージ内のさまざまなコンポーネントがどのように連携するかを説明する概要です。sphinxまたは別のパッケージを使用してdocstringからドキュメントを自動的に生成する場合、パッケージdocstringは、そのような概要を説明するのにぴったりの場所です。

その他のコンテンツについては、firecrowAlex Martelliによる優れた回答を参照してください。


実際のん__init__.pyのためのemailパッケージには、このガイドラインに従ってください?「パッケージ内のさまざまなコンポーネントがどのように連携するか」を説明するのにあまり役立たない1行のdocstringが表示されます。
Gertlex、

@GertlexたぶんWeb文書でのみ。
gerrit
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.