メモの日々


2024年09月12日(木) [長年日記]

[python] Pythonのモジュールとパッケージ

Pythonの「モジュール」と「パッケージ」という用語の使い分けがよくわからなくなる。

pipでインストールしているものはモジュールなのかパッケージなのか?importしているものはモジュールなのかパッケージなのか?

定義

Pythonの用語集には次のように書かれている。

(モジュール) Python コードの組織単位としてはたらくオブジェクトです。モジュールは任意の Python オブジェクトを含む名前空間を持ちます。モジュールは importing の処理によって Python に読み込まれます。

パッケージ を参照してください。

(パッケージ) サブモジュールや再帰的にサブパッケージを含むことの出来る module のことです。専門的には、パッケージは __path__ 属性を持つ Python オブジェクトです。

regular package と namespace package を参照してください。

パッケージの説明に「__path__ 属性を持つ Python オブジェクトです」とあるけど、英語版には「a package is a Python module with a __path__ attribute.」とある。つまり、

  • __path__ 属性を持つモジュールのことを特別にパッケージと呼ぶ

と考えればよさそう。では、__path__ 属性とは何か?

__path__ 属性

__path__ 属性については次に説明があった。

パッケージの __path__ 属性は、そのサブパッケージのインポート中に使われます。インポート機構の内部では、それは sys.path とほとんど同じように機能します。つまり、インポート中にモジュールを探す場所のリストを提供します。しかし、一般的に __path__ は sys.path よりも制約が強いです。

この説明からわかるのは、__path__ 属性はモジュールのインポート処理に使うためのものだということ。

__path__ 属性の有無を調べてみる。

% python
Python 3.12.6 (main, Sep 12 2024, 17:06:52) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, json
>>> hasattr(os, "__path__")
False
>>> hasattr(json, "__path__")
True
>>>

osモジュールはパッケージではないが、jsonモジュールはパッケージであることがわかる。

配布パッケージとインポートパッケージ

上述したことから、importしているものはモジュールだということになるだろう。

一方、pipでインストールするものはパッケージと呼ばれている気がする。

どうやら、Pythonのパッケージという用語には二種類あると考えるべきなようで、Python Packaging User Guideの次のページで説明がなされていた。

これを読むと、先に調べたPythonのパッケージは詳しくは「インポートパッケージ」であり、pipでインストールするものは「配布パッケージ」であると考えるようだ。

パッケージという言葉はあいまいなので、使い方に注意が必要そう。次の言明は正しいと言えるだろうか。

「NumPyという配布パッケージをインストールすると、numpyというモジュールをインポートできるようになる」