Pythonのimportについて、全然理解できていなかったので、自分なりにまとめてみました。
もし、間違いがありましたら、指摘していただけると嬉しいです!
動作環境
$ python3
Python 3.7.1 (default, Nov 17 2018, 02:39:57)
[Clang 10.0.0 (clang-1000.10.44.4)] on darwin
サンプルソース
一応、https://github.com/tamago324/python-import-sample/tree/master/package においてあります
$ tree
.
└── package
├── __init__.py
├── module_a.py
├── sub_package_b
│ ├── __init__.py
│ └── module_b.py
│── sub_package_c
│ ├── __init__.py
│ └── module_c.py
└── sub_package_d
├── __init__.py
└── module_c.py
モジュールとパッケージ
まずは、モジュールとパッケージについて
モジュールは、Pythonのファイル(*.py
)
パッケージは、モジュールを一つのディレクトリにまとめたもの(./package/
)。また、パッケージ内にさらにパッケージを含めることもできる(./package/sub_package_b/
)
たぶん、こんな感じだと思います。
__init__.py
importしたときに1度だけ実行されるファイル
もし、パッケージの下にさらにパッケージがある場合、__init__.py
でimportしておくべき
__init__.py
はサブモジュールをimportする役割があるのは、初めて知った。パッケージにはとりあえず空の__init__.py
をおくっていう認識だったから...
絶対import
パッケージ・モジュールはsys.path
のディレクトリから検索される
$ python3
>>> import package
>>> import package.sub_package_b
>>> from package.sub_package_c import module_c
もし、import対象のモジュール・パッケージがsys.path
のディレクトリにない場合、ModuleNotFoundError
が発生する
相対import
from
の後に.
を付けた特別なimport
のことを相対importという
また、相対importは「パッケージ内」でのみ使える
from . import module_a
from . import sub_package_b
from .sub_package_b import module_b
サブモジュールから別のサブモジュールをimport
相対importを使うことで、サブモジュールから別のサブモジュールをimportすることができる
例) package.sub_package_b
からpackage.sub_package_c
をimportする場合
from .. import module_a
from .. import sub_package_c
..
のように、上の階層に行くことができる
芋づる式にimportされている
連鎖的にimportすることもできる
from . import module_a
from . import sub_package_b
from .sub_package_b import module_b # sub_package_bをimport
from .. import module_a
from .. import sub_package_c # sub_package_cをimport
-
package/__init__.py
でpackage.sub_package_b
をimport -
package/sub_package_b/__init__.py
でpackage.sub_package_c
をimport
となっているため、package
をimportすれば、package.sub_package_c
を呼び出すことができる
$ python3
>>> import package
>>> package.sub_package_b
<module 'package.sub_package_b' from '/Users/tamago324/python-import-sample/package/sub_package_b/__init__.py'>
>>> package.sub_package_c
<module 'package.sub_package_c' from '/Users/tamago324/python-import-sample/package/sub_package_c/__init__.py'>
逆に、package.sub_package_d
はどこからもimportされていないため、明示的にimportしないと呼び出せない
>>> package.sub_package_d
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'package' has no attribute 'sub_package_d'
if __name__ == "__main__":
よくPythonのプログラムで見るif __name__ == "__main__":
について。
モジュールが直接実行された場合、__name__
には__main__
が格納されるため、このような記述になっているということ
print(f"__name__: {__name__}")
$ pwd
/Users/tamago324/python-import-sample/
$ python3 -m package.name_test
__name__: __main__
モジュールが直接実行された場合、たしかに__name__
には__main__
が入っていることが確認できた
-m
オプションを付けることでパッケージ内で相対importができるようになる(らしい)
もし、間違いがありましたら、 指摘していただけると嬉しいです!