60
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Python パッケージ作成: __init__.py の __all__ を手作業でメンテナンスしたくない

Last updated at Posted at 2017-10-14

import *__init__.py__all__ の関係

Python チュートリアル」の「6.4.1. パッケージから * を import する」を読むと、__init__.py 中に __all__ という変数を定義することで、from some_package import * とした場合に読み込まれるモジュールを制御できることが分かります。

例として、以下のパッケージ構成で考えます。

some_package/__init__.py
some_package/hoge.py
some_package/piyo.py
some_package/fuga.py

次のように some_package/__init__.py__all__ を定義します。

some_package/__init__.py
__all__ = ['hoge', 'piyo']

この場合に from some_package import * とすると、some_package.hogesome_package.piyo はインポートされますが、some_package.fuga はインポートされません。

import * でパッケージ内の全モジュールをインポートさせたい

細かく制御したい場合は __all__ に手作業でモジュール名を指定すれば良いのですが、from some_package import * としたときに「パッケージ内の全モジュールをインポートさせたい」「パッケージ内にモジュールを増やしたときに手作業で __all__ に追加するのは面倒」という場合もあると思います。

そういう場合は、__all__ を以下のように定義しておくことで、自動的に追従することができます。

some_package/__init__.py
import os, glob

__all__ = [
    os.path.split(os.path.splitext(file)[0])[1]
    for file in glob.glob(os.path.join(os.path.dirname(__file__), '[a-zA-Z0-9]*.py'))
]

他の人が作ったパッケージの場合

他の人が作ったパッケージの場合は、上記のように対応できないかもしれません。そのときは以下のような関数を作成し、import_submodules(some_package) とすることで対応できます。

import os, glob, importlib

def import_submodules(module):
    files = glob.glob(os.path.join(os.path.dirname(module.__file__), '[a-zA-Z0-9]*.py'))
    names = [os.path.split(os.path.splitext(file)[0])[1] for file in files]
    submodules = [importlib.import_module('.'.join([module.__name__, name])) for name in names]
    return submodules
60
39
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
60
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?