__init__.pyとは何ですか?
-
19-08-2019 - |
質問
Pythonソースディレクトリでの__init__.py
とは何ですか
解決
以前はパッケージの必須部分でした( old、pre -3.3 <!> quot;通常のパッケージ<!> quot; 、新しい3.3+ <!> quot; namespace package <!> quot; )。
Pythonは、通常のパッケージと名前空間パッケージの2種類のパッケージを定義します。通常のパッケージは、Python 3.2以前に存在していた従来のパッケージです。通常、通常のパッケージは、
__init__.py
ファイルを含むディレクトリとして実装されます。通常のパッケージがインポートされると、この<=>ファイルは暗黙的に実行され、定義するオブジェクトはpackage <!>#8217; s名前空間の名前にバインドされます。 <=>ファイルには、他のモジュールに含めることができるPythonコードと同じPythonコードを含めることができます。Pythonは、インポート時にモジュールに属性を追加します。
ただし、リンクをクリックするだけで、例、詳細情報、名前空間パッケージの説明、<=>のないパッケージの種類が含まれます。
他のヒント
__init__.py
という名前のファイルは、ディスク上のディレクトリをPythonパッケージディレクトリとしてマークするために使用されます。
ファイルがある場合
mydir/spam/__init__.py
mydir/spam/module.py
およびmydir
がパス上にある場合、module.py
のコードを次のようにインポートできます
import spam.module
または
from spam import module
<=>ファイルを削除すると、Pythonはそのディレクトリ内のサブモジュールを検索しなくなるため、モジュールのインポートは失敗します。
通常、<=>ファイルは空ですが、パッケージの選択した部分をより便利な名前でエクスポートしたり、便利な機能を保持したりするために使用できます。 上記の例では、initモジュールのコンテンツには
としてアクセスできますimport spam
に基づく ディレクトリをPythonパッケージとしてラベル付けし、__all__
を定義することに加えて、 __init__.py
を使用すると、パッケージレベルで任意の変数を定義できます。パッケージで何かを定義する場合、便利です。 APIのように頻繁にインポートされます。このパターンは、Pythonic <!> quot; flatはネストされた<!> quotよりも優れています。哲学。
例
これは、私のプロジェクトの1つの例です。ここでは、データベースと対話するためにsessionmaker
というSession
を頻繁にインポートしています。 <!> quot; database <!> quot;を書きました。いくつかのモジュールを含むパッケージ:
database/
__init__.py
schema.py
insertions.py
queries.py
My <=>には次のコードが含まれています:
import os
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)
ここで<=>を定義しているため、以下の構文を使用して新しいセッションを開始できます。このコードは、<!> quot; database <!> quotの内部または外部から実行されるものと同じです。パッケージディレクトリ。
from database import Session
session = Session()
もちろん、これはちょっとした便利さです-代替案は<=> quot; create_session.py <!> quot;のような新しいファイルで<=>を定義することです。データベースパッケージで、次を使用して新しいセッションを開始します。
from database.create_session import Session
session = Session()
さらに読む
<=>の適切な使用法をカバーする非常に興味深いredditスレッドがあります:
多数の意見は、<=>ファイルへの違反を避けるために<=>ファイルを非常に薄くする必要があると思われる;明示的は暗黙的<!> quotよりも優れている。哲学。
__init__.py
-
便宜上:他のユーザーは、パッケージ階層内の関数の正確な位置を知る必要はありません。
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
-
何かを初期化する場合。たとえば、ロギング(最上位に配置する必要があります):
import logging.config logging.config.dictConfig(Your_logging_config)
__init__.py
ファイルにより、Pythonはそれを含むディレクトリをモジュールとして扱います。
さらに、これはモジュールにロードされる最初のファイルなので、モジュールをロードするたびに実行するコードを実行したり、エクスポートするサブモジュールを指定したりするために使用できます。
Python 3.3以降、インポート可能なPythonパッケージとしてディレクトリを定義するために__init__.py
は不要になりました。
don <!>#8217; tが<=>マーカーファイルを必要とし、自動的に複数のパスセグメントにまたがることができるパッケージディレクトリのネイティブサポート( 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
references:
https://docs.python.org/3 /whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Python 3のパッケージには__init__.pyは必要ありませんか?
Pythonでは、パッケージの定義は非常に簡単です。 Javaと同様に、階層構造とディレクトリ構造は同じです。ただし、パッケージには__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
<=>は、存在する限り空でもかまいません。ディレクトリをパッケージと見なす必要があることを示します。もちろん、<=>は適切なコンテンツを設定することもできます。
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を関数と呼びました。次のように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
したがって*インポートを使用して、モジュールパッケージは<=>コンテンツの対象となります。
Pythonは__init__.py
ファイルがなくても機能しますが、ファイルを含める必要があります。
パッケージをモジュールとして扱う必要があると指定されているため、パッケージを含めます(空であっても)。
methods.py
ファイルを実際に使用する場合もあります:
次のファイル構造があると想像してください:
main_methods
|- methods.py
そしてfoo()
にはこれが含まれていました:
def foo():
return 'foo'
main_methods
を使用するには、次のいずれかが必要です。
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()
おそらく、import json
をjson
内に保持する必要がある(またはしたい)(たとえば、ランタイム/依存関係)が、インポートするのはLib/json/__init__.py
だけである。
<=>の名前を<=>に変更した場合、<=>をインポートするだけで<=>を使用できます:
import main_methods
print(main_methods.foo()) # Prints 'foo'
これは、<=>がパッケージの一部として扱われるため機能します。
一部のPythonパッケージは実際にこれを行います。例は JSON で、実行中の<=>は実際に<=>をインポートしています<=>パッケージから(こちらのパッケージファイル構造を参照):
ソースコード: <=>
__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
>>>
他のpythonファイルのインポートを容易にします。このファイルを、他のpyファイルを含むディレクトリ(たとえばstuff)に配置すると、stuff.otherをインポートするようなことができます。
root\
stuff\
other.py
morestuff\
another.py
ディレクトリ内でこの__init__.py
がないと、other.pyをインポートできません。Pythonがソースコードの場所を認識せず、パッケージとして認識できないためです。
__init__.py
ファイルを使用すると、インポートが簡単になります。パッケージ内にa()
が存在する場合、関数b.py
はファイル<=>から次のようにインポートできます。
from b import a
ただし、それなしでは、直接インポートすることはできません。システムパスを修正する必要があります:
import sys
sys.path.insert(0, 'path/to/b.py')
from b import a