LoginSignup
11
11

More than 5 years have passed since last update.

Pythonのimportについてわかった気になれる記事

Posted at

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は「パッケージ内」でのみ使える

package/__init__.py
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する場合

package/sub_package_b/__init__.py
from .. import module_a
from .. import sub_package_c

..のように、上の階層に行くことができる

芋づる式にimportされている

連鎖的にimportすることもできる

package/__init__.py
from . import module_a
from . import sub_package_b
from .sub_package_b import module_b     # sub_package_bをimport
package/sub_package_b/__init__.py
from .. import module_a
from .. import sub_package_c            # sub_package_cをimport
  • package/__init__.pypackage.sub_package_bをimport
  • package/sub_package_b/__init__.pypackage.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__が格納されるため、このような記述になっているということ

package/name_test.py
print(f"__name__: {__name__}")
$ pwd
/Users/tamago324/python-import-sample/

$ python3 -m package.name_test
__name__: __main__

モジュールが直接実行された場合、たしかに__name__には__main__が入っていることが確認できた

-mオプションを付けることでパッケージ内で相対importができるようになる(らしい)

もし、間違いがありましたら、 指摘していただけると嬉しいです!

参考文献

11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11