プログラムが大きくなるほど、ひとつのファイルにすべての関数を書き続けるのは大変です。
そこで役立つのがモジュールという別ファイル化の考え方です。
本記事では、Pythonの関数を別ファイル(モジュール)に分け、適切に読み込んで使う方法を初心者向けに丁寧に解説します。
Pythonモジュールとは?関数を別ファイル化する理由
モジュールの基本(関数を別ファイルに保存)
モジュールの定義
モジュールとは、Pythonのコードをまとめた1つの.py
ファイルのことです。
ふだん書いているスクリプトファイルも実はモジュールとして扱えます。
関数や定数、クラスなどを目的ごとに分けて別ファイルにすると、他のファイルからimport
して再利用できます。
基本ルール
モジュールはただのファイルなので、特別な設定は不要です。
任意の関数を定義した.py
ファイルを作成し、使いたい側のスクリプトでimport
するだけで呼び出せます。
まずは「同じフォルダに置く」シンプルな構成から始めるのがおすすめです。
メリット(再利用・見やすさ)
再利用性の向上
一度作った関数を、別のスクリプトでも繰り返し使えるようになります。
コピー&ペーストが不要になり、修正も一箇所で済むため、ミスが減り品質が上がります。
読みやすさと保守性
処理の役割ごとにファイルを分けると、どこに何が書いてあるかが明確になり、読みやすく保守しやすいコードになります。
チームでも自分でも、後から理解しやすくなります。
テストのしやすさ
モジュール単位で関数をテストできるので、不具合の切り分けが簡単になります。
最小限のコードで動作確認できるのは大きなメリットです。
いつ分けるか(処理のまとまりごと)
分ける判断基準
以下のように感じたとき、モジュール化のサインです。
同じ関数を複数ファイルで使いたい、ファイルが長くて見通しが悪い、別用途でも共通の処理がある。
「役割がひとつにまとまる」単位でファイルを分けるのが基本です。
分け過ぎへの注意
分割しすぎると逆に追いかけづらくなります。
最初は「1つの用途=1ファイル」とし、用途が自然に増えたら分割するくらいがちょうど良いです。
Pythonモジュールの作り方(ファイル作成)
ファイル名の決め方(小文字+.py)
推奨命名規則
ファイル名は小文字+アンダースコアが読みやすく、PEP 8(スタイルガイド)でも推奨されています。
例えばhelpers.py
やtext_utils.py
のようにします。
拡張子は.pyです。
NGな名前(標準モジュールと重複しない)
よくある衝突例と代替案
標準モジュールと同じ名前にすると、意図せずそれを上書き(シャドウイング)してしまいます。
例えばjson.py
を作るとimport json
が自作ファイルを読み込んでしまい、標準のjson
が使えなくなります。
避けたい名前と代替案の例は次の通りです。
NGなファイル名 | 理由(衝突する標準モジュール) | 推奨の代替例 |
---|---|---|
json.py | json | json_utils.py |
sys.py | sys | sys_tools.py |
random.py | random | rnd_utils.py |
collections.py | collections | col_utils.py |
typing.py | typing | type_helpers.py |
困ったら末尾に_utils
や_helpers
を付けて回避すると安全です。
関数を書く手順(defとreturn)
最小の流れ
- 新規に
helpers.py
を作る - 関数を
def
で定義し、結果をreturn
で返す - 保存する
以下は、文字列を返す関数と数値を返す関数を定義したシンプルなモジュールの例です。
# helpers.py
# 目的: よく使う処理を関数としてまとめたモジュール
# ポイント:
# - 関数ごとに簡単な説明(コメントやdocstring)を書くと後で理解しやすい
# - 役割を1つに絞ると再利用性が上がる
def greet(name: str) -> str:
"""名前を受け取り、挨拶文を返します。"""
# f文字列で見やすく組み立て
return f"Hello, {name}!"
def double(n: int | float) -> int | float:
"""数値を2倍にして返します。"""
return n * 2
このファイル自体は実行しても出力はありません。
出力は後述のスクリプト側で行います。
複数関数と簡単な説明
関数の上に1行コメントやdocstringを書くと、あとから何をする関数か一目で分かるのでおすすめです。
保存形式と文字コード(UTF-8)
UTF-8で保存する理由
PythonファイルはUTF-8で保存するのが標準です。
日本語のコメントや文字列を含む場合でも文字化けしにくく、他環境との互換性が高いです。
VS CodeやPyCharmなど主要なエディタはデフォルトでUTF-8です。
表示確認の例
日本語を返す関数を使う場合の出力確認例です。
エディタ・端末側のフォント設定や文字コード設定も適切にしておくと安心です。
# jp_helpers.py
def say_hello_jp(name: str) -> str:
return f"こんにちは、{name}さん"
このファイルを利用する側で印字します。
# use_jp.py
import jp_helpers
print(jp_helpers.say_hello_jp("太郎"))
こんにちは、太郎さん
フォルダ構成の基本(同じフォルダでOK)
シンプルな構成例(1スクリプト+1モジュール)
フォルダ構造
最初は「同じフォルダに置く」だけでOKです。
例えば次のような構成にします。
project_folder/
├─ helpers.py # モジュール(関数の置き場所)
└─ main.py # 実行するスクリプト
実際の使い方(最小例)
main.py
からhelpers.py
の関数を呼び出します。
# helpers.py
def greet(name: str) -> str:
"""名前を受け取り、挨拶文を返します。"""
# f文字列で見やすく組み立て
return f"Hello, {name}!"
def double(n: int | float) -> int | float:
"""数値を2倍にして返します。"""
return n * 2
# main.py
# 同じフォルダにあるhelpers.pyを読み込み
import helpers
# モジュール名.関数名 で呼び出し
message = helpers.greet("Python")
print(message)
# もちろん他の関数も呼べる
print(helpers.double(21))
Hello, Python!
42
複数に分ける命名のコツ(役割で分ける)
命名ガイド
ファイル名はその中身の責務(役割)が伝わるようにします。
「何を扱うか」が名前で分かると、探すのが早くなります。
例えば、文字列処理ならtext_utils.py
、日付関連ならdate_utils.py
のようにします。
ひとつのファイルが大きくなったら、似た処理ごとに分割していきます。
見つからない時の確認(パスと場所)
よくある原因
ModuleNotFoundError: No module named ‘xxx’が出るときは、次の原因が多いです。
ファイルが同じフォルダにない、実行している場所(カレントディレクトリ)が異なる、ファイル名のタイプミス、拡張子.py
を付け忘れ、など。
検索パスの確認
Pythonはモジュール検索パス(sys.path
)に並んだフォルダを順に探します。
現在の実行ディレクトリが先頭に入るのが一般的です。
次のスクリプトで確認できます。
# where_am_i.py
import sys
from pprint import pprint
pprint(sys.path) # Pythonがモジュールを探す順序付きのリスト
例としての出力は次のようになります。
['/path/to/project_folder',
'/usr/local/lib/python3.12',
'/usr/local/lib/python3.12/lib-dynload',
...]
自分のhelpers.py
がこのリストのどこからも辿れない場所にあると読み込めません。
まずは「同じフォルダで実行する」ことを確かめましょう。
モジュールをフォルダ分けしたい場合は、以下の記事で更に詳しく解説しています。
モジュールの使い方(importの基本)
importの書き方(同じフォルダから)
単純なimport
同じフォルダにあるhelpers.py
なら、import helpers
で読み込めます。
# sample_import.py
import helpers # helpers.py を読み込む
print("モジュールを読み込みました")
モジュールを読み込みました
モジュール名.関数名で呼び出す
呼び出しの基本形
モジュールをimportしたらモジュール名.関数名()
で呼び出します。
スコープ上の衝突を避け、どの関数かが一目で分かる利点があります。
# call_functions.py
import helpers
result1 = helpers.greet("Alice")
result2 = helpers.double(10)
print(result1)
print(result2)
Hello, Alice!
20
別名を付ける(asの使い方)
エイリアスで短く書く
モジュール名が長いときはas
で別名を付けられます。
読みやすさを保ちつつ記述を短くできます。
# alias_example.py
import helpers as h # 別名hで参照
print(h.greet("Bob"))
print(h.double(7))
Hello, Bob!
14
必要な関数だけ読む(from import)
ピンポイントで関数を取り込む
from モジュール import 関数
の形で、必要なものだけ読み込めます。
呼び出し時にモジュール名を付ける必要がなくなるので、式が短くなります。
# from_import_example.py
from helpers import greet, double # 必要な関数だけ取り込む
print(greet("Carol"))
print(double(8))
Hello, Carol!
16
名前の衝突を避ける(as)
同名の関数が他にもある場合はas
でリネームできます。
# from_import_alias.py
from helpers import greet as hello
print(hello("Dana"))
Hello, Dana!
ワイルドカードimportは避ける
from helpers import *のようなワイルドカードは、どの名前が読み込まれたか不明瞭になり、衝突の原因になります。
明示的に必要な関数だけを指定するのが安全です。
補足: 標準モジュール名と同名の自作ファイルは避けるべきだと説明しました。
同名にしてしまったときの典型的な症状は、標準機能が使えなくなることです。
例えばjson.py
が同じフォルダにある状態でimport json
をすると、標準のjson
ではなく自作のjson.py
が読み込まれます。
思わぬ動作に見えたら、まずファイル名の衝突を疑いましょう。
まとめ
モジュールは「役割ごとに関数を別ファイルへ分け、必要なときにimportして使う」ための基本単位です。
最初は同じフォルダにhelpers.py
のようなモジュールを置き、スクリプトからimport
してモジュール名.関数名()
で呼び出す流れを身につけてください。
ファイル名は小文字+アンダースコアで、標準モジュール名との衝突を避け、UTF-8で保存します。
見つからない場合はフォルダ配置とsys.path
を確認すると解決しやすいです。
慣れてきたら、処理のまとまりごとにファイルを分け、必要に応じてas
やfrom ... import ...
を使い分けると、読みやすく再利用しやすい構成を実現できます。