Pythonでパッケージをimportする際のテクニックについて

  •  
 
トビウオ2018年11月1日 - 18:02 に投稿

タグ

Pythonコードを書いていて、迷うところがあったのでまとめました。

基本的な書き方

# 「import XXX」の場合、XXXの位置にはモジュール名だけ書ける
import time

# 「from XXX import YYY」の場合、XXXにはモジュール名、YYYにはモジュール名や関数名やクラス名などを書ける
from pandas import DataFrame
from sample_module import sample_function, sample_class

## YYY部分には、ワイルドカードとして「*」も使えるが推奨されない
from sample_module import *

# モジュール名は、モジュールがパッケージ内にある(サブモジュールである)場合、.で繋げることができる。
# ただし、「from XXX import YYY」の場合、YYYがモジュール名の際は.を使用できない。
# (※パッケージはモジュールの一種)
from XXX.YYY import ZZZ  # OK
from XXX import YYY.ZZZ  # NG

# asを使うことで、言い換えることができる。NumPyなどでおなじみ
import numpy as np
from math import pi as PI

自作モジュールを読み込ませたい場合

以下、aaa.pyがbbb.pyをインポートしたいとします。

# 同一パッケージ内の場合
hoge
├── aaa.py
├── bbb.py

import bbb

# 1階層下の場合
hoge
├── aaa.py
├── ccc
│   ├── bbb.py

> 相対インポートを使う場合、「python hoge/aaa.py」といった風には実行できず、「python -m hoge.aaa」と指定して実行することになります。
> また、相対インポートを使う場合、カレントディレクトリが実行したいソースのパッケージ(今回で言えばhoge)を含まないとエラーになります。
> つまり、hogeディレクトリを子に持つディレクトリから実行するのは良いですが、hogeディレクトリやcccディレクトリに移動してから実行するとエラーになります。
> なお、相対インポートでは「.(同階層)」「..(1つ上)」「...(2つ上)」などを使用できます。
from .ccc import bbb

> 絶対インポートを使う場合、「python hoge/aaa.py」でそのまま実行できます。
> また、カレントディレクトリの位置を強制されることもありません。
> なお、絶対インポートでは、自分より同階層かそれ以下の階層のモジュールしか使用できません(sys.pathを書き換える場合を除く)。
import ccc.bbb または from ccc import bbb


# 1階層上の場合
hoge
├── bbb.py
├── ccc
│   ├── aaa.py

> 相対インポートを使う場合、「python hoge/ccc/aaa.py」といった風には実行できず、「python -m hoge.ccc.aaa」と指定して実行することになります。

from .. import bbb

> 前述したように、絶対インポートでは自分より上位の位置にあるモジュールを参照できません。
> ところが、sys.pathを書き換える場合、「python hoge/ccc/aaa.py」でそのまま実行できます。
> cccディレクトリに移動して「python aaa.py」としても問題なく実行できます。
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import bbb

# いとこの関係の場合
hoge
├── ccc
│   ├── aaa.py
│
├── ddd
│   ├── bbb.py

> 相対インポートを使う場合はこんな感じ。
> (python -m hoge.ccc.aaaはOKだが、cdしてpython -m ccc.aaaなどはNG)
from ..ddd import bbb

> sys.pathを書き換える場合はこんな感じ。
> (python hoge/ccc/aaa.pyもpython ccc/aaa.pyもpython aaa.pyもOK)
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from ddd import bbb

__init__.pyについて

  • __init__.pyはディレクトリ内に置くことで、そのディレクトリがパッケージなのだとPython処理系に認識させます
  • パッケージをimportする際、__init__.pyの中の記述が実行されます。例えば、クラスを定義しておけば、パッケージをimportした際にそのクラスを利用できます。また、サブモジュールを__init__.pyの中でimportしておけば、パッケージをimportするだけでそのサブモジュールを利用することができます
  • 通常、パッケージをimportするとパッケージ内の全オブジェクト(関数・クラス・変数など)にアクセスできますが、__init__.pyの中で「__all__ = ['aaa, bbb, ccc']」などと書くと、__all__で指定された名前のオブジェクトにのみアクセスできるようになります
  • なお、__init__.pyを省略しても、Python 3.3以降は「名前空間パッケージ」として認識されます。これは、__init__.pyを置く「通常のパッケージ」と挙動が多少異なりますが、詳しくは参考資料を参照して下さい。普段は「通常のパッケージ」のように実装するべきだと思われます。

参考資料

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。