Pythonで名前空間パッケージを作成するにはどうすればいいですか? 質問する

Pythonで名前空間パッケージを作成するにはどうすればいいですか? 質問する

Pythonでは、名前空間パッケージを使用すると、Pythonコードを複数のプロジェクトに分散できます。これは、関連するライブラリを個別のダウンロードとしてリリースする場合に便利です。たとえば、のディレクトリとPackage-1Package-2PYTHONPATH

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.pathfoo.barfoofoo.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_pathpath1path2path3sys.pathimport package.fooimport package.barimport package.baz

pkg_resources.declare_namespace(__name__)暗黙的な名前空間パッケージを含めるように更新されていません。

おすすめ記事