目次
モジュールとパッケージの違いおよびimport
今回はPythonの「import」についてです。
なんですが。
Pythonのimportを理解するには、まず「モジュール」と「パッケージ」の違いの整理が必要なので、そこからやります。
モジュールとパッケージの違い
モジュールはPythonのソースファイルです。
Pythonのソースファイル名は「モジュール名.py」ですから。
パッケージはモジュールを、packname.modulenameのような "ドット付きモジュール名" を使って参照できるようにする手段でのことです。
この「packname」にあたる部分は、Windowsでは「フォルダ」のことです。
つまり、上記は「packname」フォルダの「modulename.py」ファイルを参照するという意味になります。
でも、フォルダを作ってそこにソースファイルをただ置けば良いわけでなありません。
フォルダをパッケージとして扱えるようにするには、そのフォルダに「__init__.py」というファイルを置かねばならないというルールがあります。
この「__init__.py」ファイルは名前が正しければ、中身は空でもかまいません。
この「__init__.py」を使うやり方を「通常パッケージ」ともいいます。
他に「名前空間パッケージ」があるからですが、名前空間パッケージについてはここではふれません。
さて・・。
これらをふまえて、importです。
モジュールのimport
動作確認のため、こんな感じで適当なソースファイルを作ります。
def mod01():
print("モジュール01をインポート")
これを「imp_mod01.py」という名前をつけて保存すると、このファイルは「imp_mod01」モジュールとして、importできるようになります。
例えば、同じフォルダにもうひとつソースを作って、その中で上記のモジュール(imp_mod01)をimportして、その中のmod01()メソッドを呼びます。
import imp_mod01
# mod01モジュールを呼ぶ
imp_mod01.mod01()
これを保存して実行すると。
モジュール01をインポート
と表示されるので、モジュールが正しくimportされたのがわかります。
importで指定されたモジュールは以下の順序で検索されます。
- その名前のビルトインモジュール。
- 見つからなかった場合は sys.path にあるフォルダのリスト
この「sys.path」 のフォルダのリストには、以下がはいります:
- 入力されたスクリプトのあるフォルダ またはカレントフォルダ
- PYTHONPATH
- インストールごとのデフォルト。
上記の「imp_mod01」の場合は、sys.pathの「1.入力されたスクリプトのあるフォルダ」で見つかったというわけです。
モジュールのimportでよくある間違いが「from . import imp_mod01」のように「カレントフォルダを示すのにドットを書いてしまう」というものです。
もしモジュールに対してこう書いてしまうと。
ImportError: attempted relative import with no known parent package
のエラーでにっちもさっちもいかなくなります。
このような書き方は「パッケージ」に対してのみ可能な書き方だからです。
パッケージのimport
ということで。
今度はパッケージです。
動作確認のため、以下のようなフォルダとファイルを作ります。
フォルダは赤字、ファイルは黒字です。
__init__.py は空ファイルでいいです。
imp_pac01.pyの中身は
def pac01():
print("パッケージの1階層目です")
imp_pac02.pyの中身は
def pac02():
print("パッケージの2階層目です")
とでもしておきます。
このようにサブフォルダを作り、そこに「__init__.py」を置いたものがパッケージです。
これらのサブフォルダの下のモジュールをimportする場合は
#一階層目
import pack01.imp_pac01 as ip
#ニ階層目
import pack01.pack02.imp_pac02 as ip2
のように「.」(ドット)で連結してインポートできます。
もしくは、fromでパッケージを指定して
#一階層目
from pack01 import imp_pac01 as ip
#ニ階層目
from pack01.pack02 import imp_pac02 as ip2
みたいな感じにします。
パッケージ(ようするにサブフォルダの中)に複数のモジュール(ようするにPythonのソース)がある場合や、ひとつ上の階層のフォルダにいるモジュールをインポートする場合は以下のようにfromとドット(.)で指定する仕方もできます。
同じ階層の他のモジュールをインポート
from . import imp_pac01_other as ipo
ひとつ上の階層にあるモジュールをインポート
from .. import imp_pac01 as ip
ちなみに。
パッケージを import する際 は sys.path 上のフォルダを検索して、トップレベルのパッケージの入ったサブフォルダを探します。
ここでいうsys.path 上のフォルダというのは、前に書いたのと同じく
- 入力されたスクリプトのあるフォルダ またはカレントフォルダ
- PYTHONPATH
- インストールごとのデフォルト。
がはいっています。
まとめ
モジュールとパッケージおよびインポートについてまとめました。
実際は、sys.pathをあとで書き換えるなんて荒業もできるので、importのバリエーションはもっとたくさんあります。
でも、個人的に、あんまりimportなんかで凝る必要はないと思っているので、今回はごく基本的なことだけまとめてます。
ではでは。