こんにちは!
Pythonのパッケージって難しいですよね。
__init__.pyがあればパッケージだけど、無くても良かったりするし・・
じゃあいったい何がパッケージなんだよ!!って思いますよね
私もそう思いました。
今回はPythonのパッケージについて詳しくみていこうと思います。
少し難しい話がありますので中級者向けとしていますので気をつけてくださいねー
目次
- packageって何?
- packageの役割
- packageの作り方
- packageのインポート
- 普通のパッケージと名前空間パッケージの違い
packageって何?
複数のモジュールをまとめたのがパッケージです。
ディレクトリとファイルの関係は分かりますね。まさにあれの関係に近いです。
パッケージはモジュールを持つこともできますし、さらにパッケージを持つこともできます。
まったく同じってわけではありませんが、かなり似た関係ですので、そういうイメージとして覚えていて問題はないです。
ちなみに・・・
Pythonのバージョンが3.2以前なら、ディレクトリ内に__init__.pyが必要です。
Pythonのバージョンが3.3以降なら、__init__.pyがなくてもパッケージとして見なされます!(これを名前空間パッケージといいます)
packageの役割
パッケージ間でモジュールの名前が重複しても問題ないようにするためです。
モジュール間で、グローバル変数がかぶったとしても問題はありませんよね?
パッケージはそれと似たような感じで、モジュールの被りがあってもうまくインポートできる仕組みを作ってくれているのです。
packageの作り方
ディレクトリ内に__init__.pyがあればそれはパッケージだと言えます。
ですが、Python3.3から__init__.pyがなくともパッケージにすることができます。
それぞれのパッケージの作り方をみていきましょう
Python3.2以前
通常のパッケージの作り方になります。
これはとっても簡単で、パッケージにしたいディレクトリの下に__init__.pyを作成するだけです。
こんな感じです
.
├── caller.py
└── meta
├── __init__.py
├── spam.py
└── sub
├── egg.py
└── __init__.py
ね?簡単でしょ?
Python3.3以降
なんと・・・・・
この__init__.pyが無くてもオッケーになりました
このやり方を名前空間パッケージといいます。
さっきのコードを直すとこのようになります。
.
├── caller.py
└── meta
├── spam.py
└── sub
└── egg.py
かなり楽になってますねー!
packageのインポート
パッケージのインポートについては以下の記事でしております。
時間があれば、是非読んでください!
普通のパッケージと名前空間パッケージの違い
さて、それでは普通のパッケージと名前空間パッケージとは一体なにが異なるのでしょうか
名前空間パッケージは複数のパスに同じパッケージ名があるとPython内部で上手にまとめてくれるのです!
具体的にみてみましょう!
.
├── caller.py
└── meta
├── sub
│ └── child
│ └── descendant
│ └── spam.py
└── sub2
└── child
└── descendant
└── egg.py
caller.pyのコードは以下になります。
実行すると、NamespacePathとして__path__をPythonが管理していることがわかりますね。
この例では同じディレクトリにありますが、実際にはどこにあっても構いません。
別のファイルシステムであろうが、さらにはインターネットからも参照できます。
元々はPython3.2以前でも名前空間パッケージという概念はありました。
__init__.pyに今までは書いていたのですが、それを省略できるようになったのです。
この例を実行して、お気づきでしょうか
そうです。
パッケージとはこの__path__属性をもつモジュールのことを指します。
今まで作ったパッケージの__path__属性を確認してみましょう。必ず持っているはずです。
まとめ
いかがだったでしょうか
新しく名前空間パッケージという名前が出てきましたが、そんなに難しくないです。
要は、Python君がPathの中で同じパッケージ名があったら上手に管理してくれている仕組みなんです。
基本的に__init__.pyは書かなくていいってことです!
以上になります。
みなさんのPythonライフがよりよくなることを祈っていますね!