順番に読み進めながら学べます

モジュールとパッケージ — import で別ファイルから読み込む

モジュール(.py 1ファイル)・パッケージ・ライブラリの階層と、import math_utilityで別ファイルの関数を呼ぶ書き方を、自作モジュールを動かしながら整理します。

Python のアプリケーションは、処理を複数のファイルに分割し、それらを組み合わせて動かすのが普通です。この記事では、モジュールパッケージという単位、そして別のファイルから機能を読み込むimport文の仕組みを整理します。

モジュール・パッケージ・ライブラリの違い

Python のコードを構造化する単位は、規模順にモジュール → パッケージ → ライブラリの 3 段階に分かれます。モジュールは 1 つの .py ファイルそのもの、パッケージは複数のモジュールをまとめたフォルダ、ライブラリはさらに大きな配布単位です。

モジュール・パッケージ・ライブラリの階層
モジュール.py 1 ファイルパッケージ__init__.py 入りフォルダライブラリpandas / NumPy 等まとめる配布単位
1 ファイル(モジュール)が集まってフォルダ(パッケージ)になり、複数のパッケージが束ねられて 1 つのライブラリ(pandas / NumPy など)として配布される。
単位実体
モジュール1 つの .py ファイルmath_utility.py
パッケージ__init__.py を含むフォルダmy_app/database/
ライブラリ複数のパッケージをまとめた配布物pandas / NumPy / requests

標準ライブラリと外部ライブラリ

Python には最初から付属する標準ライブラリと、別途インストールが必要な外部ライブラリがあります。mathosjsonのような標準ライブラリは追加インストールなしでimportだけで使えます。一方、pandasrequestsなどの外部ライブラリはpip install パッケージ名でインストールしてから使います。

種類インストール代表例
標準ライブラリPython 本体に同梱(不要)math / os / sys / json / datetime
外部ライブラリpip install で追加pandas / numpy / requests

標準ライブラリの math を使って計算してみましょう。

① math.ceil(1.7) で小数点以下を切り上げた整数を表示してください。

② math.sqrt(3) で 3 の平方根を表示してください。

(正しく実行できれば解説が表示されます)

Python エディタ

コードを実行してください

自分で作ったモジュールを import する

標準ライブラリだけでなく、自分で書いた .py ファイルもモジュールとして import できます。ローカルで Python を動かすときは、main.py と読み込みたい math_utility.py を 同じフォルダに並べて置くだけで OK です。同じフォルダにあるファイルは、main.py からimport math_utilityと書くだけで読み込めます (拡張子.pyは書きません)。

ローカルでのファイル配置 (同じフォルダに並べる)
my_project/ ← プロジェクトのフォルダ
  • main.py — 実行ファイル。冒頭でimport math_utilityと書く
  • math_utility.pyadd() / multiply()を定義したモジュール
main.py と math_utility.py を同じフォルダに並べて置く。Python は実行ファイルがあるフォルダを最初に探すので、import math_utilityと書くだけで隣の math_utility.py が見つかる。サブフォルダに入れる必要はない。
import で関数が呼び出せるようになるまで
main.pyimport math_utilityPython が同フォルダからファイルを取得math_utility.add()math_utility.multiply()が呼べる読み込み要求完了
import math_utilityを書くと、Python が同じフォルダの math_utility.py を読み込み、その中の関数がmath_utility.add(...)のようにモジュール名を前置して呼び出せる状態になる。

左に math_utility.py が添付されています(📂 ファイルから中身を確認できます)。

import math_utilityで読み込んでください。

わざとモジュール名を付けずに add(10, 20)を呼んでみて、NameErrorが起きることをtry/exceptで確認してください — import math_utilityだけでは、main 側のスコープに入るのはmath_utility という名前だけで、addはそのまま呼べないからです。

③ 続けて、math_utility.add(10, 20)math_utility.multiply(5, 5)モジュール名を前置した正しい呼び方で print() してください。

Python エディタ

コードを実行してください

import 時にファイル全体が実行される

import math_utilityを書くと、Python は math_utility.py を上から下まで一度実行します。関数定義(def)はそのときにメモリ上に登録され、後からmath_utility.add(...)のように呼び出せる状態になります。関数の中身が実行されるわけではないのがポイントで、import の段階で動くのは関数定義の外に書かれたコード(モジュールトップレベルの処理)だけです。

外部ファイルから関数を読み込む流れ
main.pyimport math_utilitymath_utility.py を上から下まで実行math_utility.add()を呼び出せる読み込み完了後
main.py がimport math_utilityに到達した瞬間、Python は math_utility.py を上から下まで一度実行する。defで書かれた関数定義はメモリに登録され、後からmath_utility.add(...)で呼び出せる状態になる。

import で重い処理が走らないように注意

トップレベルとは、関数や class の中ではなく、ファイルの一番外側(インデントが付かない位置)に直接書かれたコードのことです。import すると Python はこのトップレベルを上から順に実行します。ここで重い処理(DB 接続・大きなファイル読み込み・無限ループなど)を書いてしまうと、import するだけで時間がかかってしまいます。実行は関数の中に閉じ込め、トップレベルには関数定義と最低限の初期化だけを書きましょう。

直接実行とインポートを区別する __name__

Python のファイルは大きく 2 つに分かれます — 直接実行するファイルpython xxx.pyで起動するファイル)と、他のファイルから import されるファイル(モジュールとして読み込まれるファイル)です。同じファイルでも、どちらの立場で動いているかを判定したい場面はよくあります — たとえば「直接実行されたときだけ動作確認用のコードを走らせたい」というケースです。

この判定には、Python が自動で用意する特殊変数__name__を使います。直接実行されたファイルでは__name__の値が"__main__"になり、import されたファイルではモジュール名(ファイル名)になります。if __name__ == "__main__":の中に書いた処理は、そのファイルを直接実行したときだけ動きます。

__name__ の値は実行のされ方で変わる
__name__(自動でセットされる特殊変数)直接実行python xxx.py__name__= "__main__"importされる__name__= "xxx"(モジュール名)
Python が自動でセットする特殊変数__name__は、python xxx.py直接実行すると"__main__"、別ファイルからimportされるとモジュール名(ファイル名)になる。
# math_utility.py
def add(a, b):
    return a + b


# 直接実行されたときだけ動作確認を走らせる
if __name__ == "__main__":
    print("動作確認:", add(10, 20))   # 30

# 他のファイルから import math_utility された場合は、
# 上の if ブロックは実行されない(add 関数だけ提供される)

添付された math_utility_2.py には、自分の__name__を表示するshow_name()関数と、末尾にif __name__ == "__main__":ブロックが書かれています(📂 で中身を確認)。

① main 側で math_utility_2 を import し、main の__name__を print() で表示してください。

② math_utility_2.show_name() を呼んで、import 経由で読み込まれた側の__name__がどう違うか確認してください。

Python エディタ

コードを実行してください

複数の自作モジュールを組み合わせる

実際のアプリケーションでは、関数を役割ごとに別ファイルに分けて配置し、main.py からまとめて読み込むのが基本パターンです。たとえば、入力チェックはvalidator.py、表示用の整形はformatter.py、というように責務を分割します。こうしておくと「整形ルールだけ後から変えたい」「検証ロジックを増やしたい」となっても、該当ファイルだけ書き換えれば済み、main.py は触らずに変更を吸収できます。

main.py が 2 つの自作モジュールを使う
main.pyimport validatorimport formattervalidator.pyis_valid_price()formatter.pyformat_price()importimport
main.py からimport validatorimport formatterで 2 つのモジュールを読み込み、それぞれの関数を組み合わせて 1 つの処理を作る。

添付の validator.py と formatter.py の中身を完成させて、main.py から両方を import して使います。

① validator.py の is_valid_price(price) を実装してください — price が0 より大きい intなら True、それ以外は False を返す。

② formatter.py の format_price(price) を実装してください — 整数を受け取り、5% の税を加えた金額 int(price + price * 0.05)を計算して "税込 ¥1575" のような文字列を返す。

③ main.py で両方を import し、price = 1500 が valid かを判定してから整形して print() してください。

Python エディタ

コードを実行してください

この記事ではモジュール・パッケージ・ライブラリの階層、import文で別ファイルの関数を呼び出す書き方、import 時にファイル全体が実行されるしくみ、__name__ == "__main__"で直接実行とインポートを区別するパターン、そして複数の自作モジュールを役割ごとに分割して組み合わせる構成を学びました。次の記事では__init__.pyを扱います。

QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1次の説明のうち、モジュール / パッケージ / ライブラリの対応として正しいものはどれですか?

Q2math_utility.py の中にprint("hello")をトップレベルで書いておきました。別のファイルからimport math_utilityを実行すると、画面には何が表示されますか?

Q3次のコードを直接実行したときと、別のファイルからimport したときの挙動として正しい組み合わせはどれですか?
if __name__ == "__main__":
print("hello")