Python
module

Pythonの下位モジュールの扱い

More than 1 year has passed since last update.

聞かれたときに間違えて答えて恥しかったのでメモしておく。
事の発端はscipy.specialが参照できなかったという話。
つまりこういうことだった。

import scipy as sci

sci.special # AttributeError

import scipy.special
scipy.special # Not error

上のパターンでエラーが起きるとは思ってなかったので面喰らった。
調べてみた。

下位モジュール

Pythonではあるモジュールの内側に別のモジュールをネストさせられる。
いままで上位のモジュールをインポートしたら下位のモジュールも参照できるのが当然だと思っていたけどどうも違うらしい。
テストするために簡単なモジュールを作成した。

テスト

こんな感じの構成になった。
使ったのはpython3.6.1。

test.py
test1/
    __init__.py
    test2/
        __init__.py
test.py
import test1

print(dir(test1))

# callable
test1.func_in_test1()

# not callable
try:
    test1.test2.func_in_test2()
except AttributeError as e:
    print("Error!")

import test1.test2
print(dir(test1))

# callable here
test1.test2.func_in_test2()
test1/__init__.py
def func_in_test1():
    print('test1')
    return
test2/__init__.py
def func_in_test2():
    print('test2')
    return

test.pyを動かしてテストしてみた、出力は以下のようになった。

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'func_in_test1']
test1
Error!
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'func_in_test1', 'test2']
test2

下位モジュールの関数を見れていないし、そもそも下位モジュール自体が名前空間(で合っているんだろうか?)に含まれていない。
下位のモジュールを使う場合には明示的にインポートしないといけないらしい。
おそらく、外部には公開しない内部向けのモジュールのためにそうなっているのだと思う。
ちなみに、test1/__init.py__内でインポートしたモジュールは問題なく参照できる。

知らんかった。