__init__.pyの目的は何ですか?


回答:


1454

以前はパッケージの必須部分でした(古い3.3より前の「通常のパッケージ」ではなく、新しい3.3 以降の「名前空間パッケージ」)。

ここにドキュメントがあります。

Pythonは、通常のパッケージと名前空間パッケージの2種類のパッケージを定義しています。通常のパッケージは、Python 3.2以前に存在していた従来のパッケージです。通常のパッケージは、通常、__init__.pyファイルを含むディレクトリとして実装されます。通常のパッケージがインポートされると、この__init__.pyファイルは暗黙的に実行され、ファイルが定義するオブジェクトはパッケージの名前空間の名前にバインドされます。この__init__.pyファイルには、他のモジュールと同じPythonコードを含めることができます。Pythonは、インポート時にモジュールに属性を追加します。

しかし、リンクをクリックするだけで、例、詳細情報、および名前空間パッケージの説明が含まれます__init__.py


187
これはどういう意味ですか:「これは、文字列などの一般的な名前のディレクトリが、後でモジュール検索パスで発生する有効なモジュールを誤って非表示にしないようにするために行われます」?
カールG

97
@CarlG Pythonは、ディレクトリのリストを検索して、たとえばインポート文の名前を解決します。これらは任意のディレクトリにすることができ、エンドユーザーが任意のディレクトリを追加できるため、開発者は、ドキュメントの例の「文字列」など、有効なPythonモジュールと名前を共有するディレクトリについて心配する必要があります。これを軽減するために、空白であっても、_ _ init _ _.py(スペースなし)という名前のファイルを含まないディレクトリは無視されます。
2ビットの錬金術師

186
@CarlGこれを試してください。「datetime」というディレクトリを作成し、その中に2つの空のファイル、init.pyファイル(アンダースコア付き)とdatetime.pyを作成します。次に、インタープリターを開いてsysをインポートし、を発行してsys.path.insert(0, '/path/to/datetime')、そのパスを、作成したディレクトリへのパスに置き換えます。今のようなものを試してくださいfrom datetime import datetime;datetime.now()。AttributeErrorが表示されるはずです(現在、空のファイルをインポートしているためです)。空の初期化ファイルを作成せずにこれらの手順を繰り返すと、これは起こりません。それはそれが防ぐことを意図したものです。
2ビットの錬金術師

4
@DarekNędzaPythonインタープリターを単に開いてfrom datetime import datetimeエラーなしで発行できない場合、何かが正しく設定されていません。バージョン2.3までは、これで十分です。
2ビットの錬金術師

5
@SWang:不正解です。組み込みモジュールではなく、組み込み関数クラスがbuiltinsリストされます(docs.python.org/3/tutorial/modules.html#the-dir-functionを参照)。組み込みモジュールを一覧表示する場合は、(cf。docs.python.org/3/library/sys.html#sys.builtin_module_names)を実行します。import sys; print(sys.builtin_module_names)
Maggyero

842

名前__init__.pyが付けられたファイルは、ディスク上のディレクトリをPythonパッケージディレクトリとしてマークするために使用されます。ファイルがある場合

mydir/spam/__init__.py
mydir/spam/module.py

そしてmydir、あなたのパス上にある、あなたは、内のコードをインポートすることができますmodule.pyように

import spam.module

または

from spam import module

__init__.pyファイルを削除すると、Pythonはそのディレクトリ内のサブモジュールを検索しなくなるため、モジュールのインポートは失敗します。

__init__.pyファイルは通常空であるが、例えば上述した等方が便利名、ホールド簡易関数、下のパッケージの選択された部分をエクスポートするために使用することができ、初期化モジュールの内容は、以下のようにアクセスすることができ

import spam

基づいて、この


96
更新:このファイル__init__.pyはPython 2.Xで必要でしたが、Python 2.7.12(私はテストしました)でも必要ですが、(申し立てによると)Python 3.3以降では不要になり、Python 3.4.3(Iそれをテストした)。詳細については、stackoverflow.com / questions / 37139786をご覧ください。
Rob_before_edits

4
使用しないでください。これは「名前空間」パッケージであり、通常のパッケージではありません。名前空間パッケージは、非常にまれなユースケースで使用されます。いつ使用するかを知る必要はありません。だけを使用してください__init__.py
メタン

2
ただし、所有setup.pyしていて使用するfind_packages()場合は__init__.py、すべてのディレクトリに存在する必要があります。stackoverflow.com/a/56277323/7127824を
techkuz

484

Pythonパッケージとしてディレクトリを標識し、定義するだけで__all____init__.pyあなたは、パッケージレベルで任意の変数を定義することができます。これは、パッケージがAPIのような方法で頻繁にインポートされるものを定義している場合に便利です。このパターンは、Pythonの「フラットは入れ子よりも優れている」という哲学の遵守を促進します。

以下は、私のプロジェクトの1つの例です。ここでは、データベースとやり取りするためにsessionmaker呼び出されたものを頻繁にインポートSessionしています。いくつかのモジュールを含む「データベース」パッケージを作成しました。

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

__init__.pyには次のコードが含まれています:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Sessionここで定義したので、以下の構文を使用して新しいセッションを開始できます。このコードは、「データベース」パッケージディレクトリの内部または外部から実行されるコードと同じです。

from database import Session
session = Session()

もちろん、これは少し便利です。代わりSessionに、データベースパッケージの「create_session.py」のような新しいファイルで定義し、次を使用して新しいセッションを開始します。

from database.create_session import Session
session = Session()

参考文献

__init__.pyここの適切な使用法をカバーする非常に興味深いredditスレッドがあります。

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

大多数の意見は__init__.py、「明示的なものは暗黙的なものよりも優れている」という哲学に違反しないようにするために、ファイルは非常に薄くすべきであると思われます。


3
enginesessionmakercreate_engine、およびosすべてのもからインポートすることができdatabaseますが、その名前空間の混乱を作ったようになりました...ようです。
ArtOfWarfare 2015

9
@ArtOfWarfareを使用__all__ = [...]すると、でインポートされるものを制限できますimport *。しかし、それとは別に、はい、厄介なトップレベルの名前空間が残ります。
Nathan Gould

「データベースURL」とは何ですか?create_engineを「mysql + mysqldb:// root:python @ localhost:3306 / test」で囲むことでこれを複製しようとしましたが、機能しません。ありがとう。
SunnyBoiz

2
quieries.pyなどのパッケージ内から、initで定義された「Session」クラスにどのようにアクセスしますか?
vldbnc

253

2つの主な理由があります __init__.py

  1. 便宜上、他のユーザーは、パッケージ階層内での関数の正確な場所を知る必要はありません。

    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    # in file1.py
    def add():
        pass

    その後、他の人がadd()を呼び出すことができます

    from your_package import add

    のようなfile1を知らずに

    from your_package.file1 import add
  2. 初期化したいものがあれば; たとえば、ロギング(最上位に配置する必要があります):

    import logging.config
    logging.config.dictConfig(Your_logging_config)

7
ああ、あなたの答えを読む前に、その場所から明示的に関数を呼び出すのは良い習慣だと思いました。
Aerin

2
@Aerinは、短いステートメント(または、この場合は主観的な結論)が常に正しいとは見なさない方がよいでしょう。からのインポート__init__.pyが役立つ場合もありますが、すべての場合に役立つわけではありません。
トビアスセッテ

2
これらのコードはインポート時または実行時に実行されますか?
user1559897

111

この__init__.pyファイルにより、Pythonはそれをモジュールとして含むディレクトリを扱います。

さらに、これはモジュールに読み込まれる最初のファイルなので、モジュールが読み込まれるたびに実行するコードを実行したり、エクスポートするサブモジュールを指定したりできます。


89

Python 3.3以降__init__.py、インポート可能なPythonパッケージとしてディレクトリを定義する必要がなくなりました。

PEP 420:Implicit Namespace Packagesを確認してください:

__init__.pyマーカーファイルを必要とせず、自動的に複数のパスセグメントにまたがることができるパッケージディレクトリのネイティブサポート(名前空間パッケージへのさまざまなサードパーティのアプローチに触発され、PEP 420で説明されています)

ここにテストがあります:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

参照:
https : //docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is __init__。 Python 3のパッケージにはpyは不要ですか?


3
「名前空間」パッケージです。通常のパッケージには使用しないでください。
メタン

@メタン、コメントについて詳しく教えてください。
Robert Lugg、

3
@RobertLugg参照くださいdev.to/methane/don-t-omit-init-py-3hga
メタン

57

Pythonでは、パッケージの定義は非常に単純です。Javaと同様に、階層構造とディレクトリ構造は同じです。ただし__init__.py、パッケージに含める必要があります。__init__.py以下の例でファイルを説明します。

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py存在する限り、空にすることができます。ディレクトリをパッケージと見なす必要があることを示します。もちろん、__init__.py適切なコンテンツを設定することもできます。

module_n1に関数を追加すると、

def function_X():
    print "function_X in module_n1"
    return

実行後:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

次に、階層パッケージに従い、module_n1を関数と呼びました。__init__.py次のようにsubPackage_bで使用できます。

__all__ = ['module_n2', 'module_n3']

実行後:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

したがって、*インポートを使用すると、モジュールパッケージは__init__.pyコンテンツの対象になります。


setup.pyは、パッケージ化されたライブラリを介して同じインポートをどのように実行するように見えますか? from package_x.subPackage_b.module_n1 import function_X
テクナジ

したがって、ここで重要なことは、「使用*インポート、モジュールパッケージはinit .pyコンテンツの対象になる」
Minnie

54

Pythonは__init__.pyファイルなしでも機能しますが、ファイルを含める必要があります。

これは、パッケージをモジュールとして扱う必要があることを指定するため、パッケージを含めます(空の場合でも)。

実際に__init__.pyファイルを使用する場合もあります:

次のファイル構造があるとします。

main_methods 
    |- methods.py

そしてmethods.pyこれを含んだ:

def foo():
    return 'foo'

使用foo()するには、次のいずれかが必要です。

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

たぶん、そこには必要な(またはしたい)維持するためにmethods.py内部main_methods(例えばランタイム/依存関係を)しかし、あなただけインポートしたいですmain_methods


の名前をmethods.pytoに変更した場合は、インポートするだけで__init__.py使用できます。foo()main_methods

import main_methods
print(main_methods.foo()) # Prints 'foo'

これ__init__.pyはパッケージの一部として扱われるため機能します。


一部のPythonパッケージは実際にこれを行います。例はJSONであり、実行import jsonは実際にパッケージ__init__.pyからインポートされjsonます(パッケージファイルの構造はこちらを参照してください):

ソースコード: Lib/json/__init__.py


39

__init__.py あるディレクトリをロード可能なモジュールとして扱います。

コードを読むことを好む人のために、私はTwo-Bit Alchemistのコメントをここに置きます。

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

30

他のpythonファイルのインポートを容易にします。このファイルを他のpyファイルを含むディレクトリ(たとえばstuff)に配置すると、import stuff.otherのようなことができます。

root\
    stuff\
         other.py

    morestuff\
         another.py

__init__.pyディレクトリstuff内にこれがないと、Pythonはstuffのソースコードの場所がわからず、それをパッケージとして認識できないため、other.pyをインポートできませんでした。


2
私のプロジェクト(python 3.4)で同じ構造を持っていますが、another.pyにother.pyを表示させることができません。インポートするにはどうすればよいですか?root.stuffから他のインポート?VSCodeデバッグモードでは機能しますが、コマンドラインでは機能しません。何か案は?
rodrigorf 2018年

10

__init__.pyファイルには、輸入が容易になります。__init__.pyパッケージ内にが存在する場合、関数a()は次のようにファイルからインポートできますb.py

from b import a

ただし、それがないと、直接インポートすることはできません。システムパスを修正する必要があります。

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a

関数a()はファイルb.py [snippet]からインポートできますが、それがないと直接インポートできません」とはどういう意味ですか?__init__.pyなしでファイルa。から関数a()をインポートできます。
aderchox
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.