Python プログラミング

[Python] __init__.pyの役割とは?パッケージ化やimportの関係は?

投稿日:

こんにちは!シミダイ(@shimidai2100)です。

中規模~大規模のプロジェクトを作成する時に必要なパッケージ化ですが、その際に必要になってくるのが「__init__.py」です。

また自分で作成したパッケージを公開する時も必須となるファイルになります。

FlaskDjangoなどを勉強し始めた時に「__init__.py」とは何だ?という人は、ぜひこの記事を読んで参考にしてみてください。


__init__.pyの役割とは?

ずばり「__init__.py」ファイルはパッケージをimportする時の初期化処理を行うファイルになります。

皆さんも「numpy」や「pandas」などのパッケージも同様に、「import」する時に「__init__.py」を読み込んでいます。

では具体的な例を絡めて説明していきます。

では「pandas」の例で確認してみましょう。※以下はpandasのGithubになります。

赤枠のように「__init__.py」でpandasを初期化しているのが分かります。

pandasのパッケージで「__init__.py」があることを確認

では「pandas」を「import」するコードで確認してみます。

先ほど「__init__.py」はパッケージをimportする時の初期化処理を行うファイルと説明しました。

つまり、内部的には以下の処理をやっていることになります。

  1. pandasディレクトリをインポート
  2. pandasをインポート時に「__init__.py」が存在するので初期化

という処理をしていることになります。

普段何気なく「pandas」を「import」していますが、実は内部的にはこんな処理が行われています。

では、実際に「pandas」の「__init__.py」のコードを確認してみます。

「__init__.py」でどのように初期化されているか確認

40行目~52行目で「pandas」内の各種モジュールをインポートしているのが分かります。

そのため、以下のように「pandas」だけインポートしても「DataFrame」や「read_csv」を使うことが出来るというわけです。

理解されましたでしょうか?

実際に「__init__.py」を使用して、パッケージを作成してみる。

では実際にパッケージを作成してみたいと思います。

今回は以下の構成でパッケージを作成したいと思います。

sample/
├ __init__.py
└api.py

ではそれぞれのファイルとソースの中身を確認してみましょう。

__init__.py」では単純にsampleパッケージ内にある、すべての関数や定数などを読み込んでいるだけです。

これですべての「from api import *」とすることで「api.py」にある関数定数値にアクセスすることができるようになります。

次に「api.py」を確認してみましょう。

「api.py」では定数値「CONST_VALUE」と関数「show_today()」が定義されています。

これでパッケージの作成は完了しました。

では実際にプログラムを動かしてみましょう。

今回は「sample」フォルダと同じ階層に移動して、インタプリタで実行してみたいと思います。

以下が実行結果になります。

>>> import sample
>>> sample.api.show_today()
2019-01-29
>>> print(sample.api.CONST_VALUE)
THIS IS TEST!

このように「__init__.py」を理解し、有効的に活用することで簡単にパッケージ化することができます。

補足:「__init__.py」がないパッケージはどうなるのか?

結論からいうと「__init__.py」がなくてもパッケージとしては機能します。

ただし、パッケージを利用する上でとても使いにくいなります。

では「__init__.py」が無い場合は、どのようにアクセスするか確認してみましょう。

今回は以下の構成でパッケージを作成したいと思います。

sample/
└api.py

今回も「sample」フォルダと同じ階層に移動して、インタプリタで実行してみたいと思います。

>>> import sample
>>> sample.api.show_today()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'sample' has no attribute 'api'
>>> print(sample.api.CONST_VALUE)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'sample' has no attribute 'api'

先ほどと同じコードなのに、「AttributeError」(定義されていませんエラー)が発生しました。

これは「sample」パッケージを読み込んだ時点で、配下にあるPythonファイル群を読み込んだ初期化処理がされていないために発生します。

では、「api」にはアクセスすることはできないのでしょうか?

そんなことはなく、以下のように書けばアクセスすることができます。

>>> from sample import api
>>> api.show_today()
2019-01-29
>>> print(api.CONST_VALUE)
THIS IS TEST!

これはパッケージとしてimportしているのではなく、単純なPythonファイルを読み込んでいます。

パッケージ化にしないとPythonファイルをすべてimportする必要があり、冗長なコーディングになります。

そのためでパッケージ化を行う時は「__init__.py」が重要になってくるわけです。

スポンサードリンク

関連記事

-Python, プログラミング

Translate »

Copyright© shimidai2100 , 2019 All Rights Reserved.