Pythonでは、名前空間パッケージを使用すると、Pythonコードを複数のプロジェクトに分散できます。これは、関連するライブラリを個別のダウンロードとしてリリースする場合に便利です。たとえば、のディレクトリとPackage-1
でPackage-2
はPYTHONPATH
、
Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py
エンドユーザーは、 および を行うことができimport namespace.module1
ますimport namespace.module2
。
複数の Python 製品がその名前空間でモジュールを定義できるように名前空間パッケージを定義する最適な方法は何ですか?
ベストアンサー1
要約:
Python 3.3 では、何もする必要はありません。__init__.py
名前空間パッケージ ディレクトリに何も置かなければ、そのまま動作します。3.3 より前では、将来性があり、暗黙の名前空間パッケージとすでに互換性があるため、1 つのpkgutil.extend_path()
ソリューションよりも 1 つのソリューションを選択してください。pkg_resources.declare_namespace()
Python 3.3では暗黙的な名前空間パッケージが導入されました。ペップ420。
つまり、 によって作成できるオブジェクトの種類は次の 3 つになりますimport foo
。
foo.py
ファイルで表されるモジュール- 通常のパッケージは、ファイル
foo
を含むディレクトリによって表されます__init__.py
- 名前空間パッケージ。ファイル
foo
のない1 つ以上のディレクトリで表されます。__init__.py
パッケージもモジュールですが、ここでの「モジュール」は「非パッケージ モジュール」を意味します。
まず、sys.path
モジュールまたは通常のパッケージをスキャンします。成功した場合は、検索を停止し、モジュールまたはパッケージを作成して初期化します。モジュールまたは通常のパッケージが見つからなかったが、少なくとも 1 つのディレクトリが見つかった場合は、名前空間パッケージを作成して初期化します。
モジュールと通常のパッケージは、作成元のファイル__file__
に設定されます。通常のパッケージと名前空間パッケージは、作成元のディレクトリに設定されます。.py
__path__
を実行するとimport foo.bar
、まず に対して上記の検索が行われ、次に パッケージが見つかった場合は、の代わりに を検索パスとして使用して のfoo
検索bar
が行われます。が見つかった場合は、と が作成され、初期化されます。foo.__path__
sys.path
foo.bar
foo
foo.bar
では、通常のパッケージと名前空間パッケージはどのように混在するのでしょうか? 通常は混在しませんが、古いpkgutil
明示的な名前空間パッケージ方式が拡張され、暗黙的な名前空間パッケージも含まれるようになりました。
次のような既存の通常パッケージがある場合__init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
...従来の動作では、他の通常検索されたパス上のパッケージを に追加します__path__
。ただし、Python 3.3 では、名前空間パッケージも追加されます。
したがって、次のディレクトリ構造を持つことができます。
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
...そして、2 つの行に (および、およびが内にある)が__init__.py
ある限り、、およびはすべて機能します。extend_path
path1
path2
path3
sys.path
import package.foo
import package.bar
import package.baz
pkg_resources.declare_namespace(__name__)
暗黙的な名前空間パッケージを含めるように更新されていません。