プロジェクトが大きくなると関数を別ファイルに分けて管理したくなります。
Pythonではimport
を使うことで、他のファイルの関数を簡単に呼び出せます。
この記事では、同じフォルダやフォルダ分け(パッケージ)からのimport
の基本と実践、そして初心者がつまずきやすいエラーの対処法まで、手を動かしながら理解できるよう丁寧に解説します。
importの基本(Pythonで別ファイルの関数)
モジュールとは 別ファイルを読み込む仕組み
Pythonでは、1つの.py
ファイルがそのまま「モジュール」になります。
モジュールをimport
すると、その中で定義された関数や変数、クラスを参照できます。
ポイントは「ファイルが境界」だという点です。
ファイル名がそのままモジュール名になります。
モジュールに関係する用語は次の通りです。
用語 | 説明 |
---|---|
モジュール | 1つの.py ファイルのこと |
パッケージ | モジュールをまとめるフォルダのこと。Python 3.3以降は__init__.py がなくても「名前空間パッケージ」として扱えますが、初心者は付けておくと明示的で安全です |
絶対import | プロジェクトのルートからのパスでimport するやり方 |
相対import | from .something import x のようにドットで相対位置を指定するやり方 |
注意として、モジュールのファイル先頭直下にあるコード(トップレベルのコード)はimport
しただけで実行されます。
副作用のある処理は避け、関数にまとめるのが安全です。
最小のファイル構成例
最小構成は「関数を定義するファイル」と「それを使うファイル」の2つです。
project/
├─ utils.py ← 関数を定義
└─ main.py ← 関数を呼び出す
まずは関数を定義する側です。
# utils.py
# 2つの数値を足し合わせる関数を定義します。
def add(a, b):
"""a と b を足した結果を返します。"""
return a + b
次に、import
で別ファイルの関数を使います。
# main.py
# 同じフォルダ内の utils モジュールを読み込み、関数 add を使います。
import utils # ファイル名 utils.py をモジュールとして読み込む
result = utils.add(2, 3) # モジュール名.関数名 で呼び出し
print("2 + 3 =", result)
2 + 3 = 5
この例が「別ファイルの関数を使う」の最小形です。
以降では、より便利な書き方やフォルダ分けされたプロジェクトでの扱いを詳しく説明します。
同じフォルダから関数をimport
import モジュール名 と モジュール名.関数で呼び出す
import utils
のようにモジュール全体を読み込み、utils.add()
の形で呼び出す基本形です。
衝突しにくく、名前の出どころが明確なので読みやすいコードになります。
# main.py
import utils # モジュール全体を読み込む
print(utils.add(10, 5)) # utils.add で関数を呼ぶ
15
- 初心者はまずこの書き方から覚えると安全です。
- 同じ名前の関数が複数のモジュールにあっても、
utils.add
のように明示できるため混乱しません。
from モジュール名 import 関数名 で直接使う
必要な関数だけを直接インポートして、add(…)
と短く書けます。
短いが衝突には注意です。
# main.py
from utils import add # 関数だけを読み込む
print(add(7, 8)) # 直接呼び出せる
15
- 同名の
add
が他にもある場合に衝突しやすいです。 - 大きめのスクリプトでは、どのモジュールの関数なのか分かりにくくなることがあります。
asで別名を付ける 使いやすくする
as
で別名を付けると、長いモジュール名や関数名を短くできます。
# main.py
import utils as u # モジュールに別名
from utils import add as addi # 関数に別名
print(u.add(3, 4)) # 7
print(addi(5, 6)) # 11
7
11
- 別名は短く、かつ意味が推測できるものにします。
- チーム開発ではプロジェクト内での別名の慣習(例:
import numpy as np
)に合わせると可読性が上がります。
複数の関数をまとめてimportする書き方
カンマで区切って複数の関数を読み込めます。
# main.py
from utils import add, subtract # 2つの関数を一度に読み込む
print(add(10, 2))
print(subtract(10, 2))
12
8
import * は非推奨 初心者は使わない
from utils import * は使わないでください。
どの名前がどこから来たのか分からなくなり、バグの温床になります。
型チェッカや補完精度も下がり、コードレビューも難しくなります。
明示的に必要なものだけをインポートしましょう。
代表的な書き方の比較
書き方 | 呼び出し例 | 特徴 |
---|---|---|
import utils | utils.add() | 安全で読みやすい。推奨の基本形 |
from utils import add | add() | 短いが衝突しやすい。小規模で有効 |
import utils as u | u.add() | 長いモジュール名に有効。別名は慎重に |
from utils import * | add() | 非推奨。名前空間を汚染する |
フォルダ分け(パッケージ)からのimport
プロジェクト構成例 フォルダ配下のモジュール
フォルダにモジュールをまとめると見通しが良くなります。
初心者は__init__.py
を置いて明示的なパッケージにすると安定です。
myproject/
├─ app/
│ └─ main.py
└─ myutils/
├─ __init__.py ← 空でもOK。パッケージのしるし
├─ calc.py
└─ text.py
モジュール例:
# myutils/calc.py
def add(a, b):
return a + b
def subtract(a, b):
return a - b
# myutils/__init__.py
# 明示的に公開する名前をまとめたい場合は __all__ を使います。
# 初心者は空ファイルで大丈夫です。
__all__ = ["calc", "text"] # 参考。なくても動きます。
from フォルダ名 import モジュール名
パッケージ直下のモジュールをインポートして使います。
# app/main.py
from myutils import calc # フォルダ(myutils)配下のモジュール(calc)を読み込む
print(calc.add(2, 3))
print(calc.subtract(9, 4))
5
5
from フォルダ名.モジュール名 import 関数名
さらに関数単位で読み込めます。
# app/main.py
from myutils.calc import add, subtract # 関数を直接読み込む
print(add(100, 1))
print(subtract(100, 1))
101
99
ルートから実行する パスの注意
パッケージを使う時は「プロジェクトのルートから」実行するのが基本です。
特に複数階層のfrom パッケージ import モジュール
を使う場合、作業ディレクトリがずれるとModuleNotFoundError
になりやすくなります。
正しい実行例
# ルート(myproject)に移動してから実行
cd myproject
python -m app.main
-m
オプションを使うと、パッケージ解決をPythonに任せられるため、sys.path
の扱いが安定します。
間違えやすい実行例
# app ディレクトリで直接ファイルを実行すると、myutils が見つからないことがある
cd myproject/app
python main.py # ← ModuleNotFoundError になりがち
必要なら下記のようにパスの状態を確認できます。
# app/main.py
import sys
print("sys.path の先頭:", sys.path[0]) # 実行ディレクトリが入る
sys.path の先頭: /absolute/path/to/myproject
相対importは避ける 初心者向けの推奨
from .calc import add
のような相対importは、ファイルの位置に依存して壊れやすく、移動やテストで混乱しがちです。
初心者は「絶対import」を一貫して使うことをおすすめします。
- 相対:
from .calc import add
ではなく - 絶対:
from myutils.calc import add
を使う
よくあるエラーと対処(ModuleNotFoundErrorなど)
ModuleNotFoundError の原因と確認ポイント
ModuleNotFoundError: No module named 'xxx'
は、モジュールを見つけられない時のエラーです。
次を確認します。
- 実行場所がプロジェクトルートか
→cd
でルートへ移動し、python -m パッケージ.モジュール
で実行します。 - パッケージに
__init__.py
があるか
→ Python 3.3以降は省略可能ですが、初心者は置いておくと安全です。 - ファイル名やフォルダ名のスペルに誤りがないか
→ 大文字小文字も一致しているか確認します。 - venvなど実行しているPython環境が合っているか
→ VS CodeやターミナルのPythonが意図した環境か確認します。 - 同名ファイルが近くにあって衝突していないか
→ 例: 自作のrandom.py
が標準ライブラリrandom
を隠している。
再現と修正例
cd myproject/app
python main.py
# → ModuleNotFoundError: No module named 'myutils'
問題が起きる場合は、-mをつけた方法で実行します。
cd myproject
python -m app.main
# → 正常に動く
ImportError 名称のスペルミスに注意
ImportError: cannot import name 'xxx' from 'yyy'
は、モジュール自体は見つかったが、その中に目的の名前が存在しないときに起きます。
関数名のスペルミスや、ファイル側でまだ定義していない場合が原因です。
再現コード
# myutils/calc.py
def add_numbers(a, b):
return a + b
# app/main.py
from myutils.calc import add # 存在しない名前を指定している
print(add(1, 2))
Traceback (most recent call last):
...
ImportError: cannot import name 'add' from 'myutils.calc' (myutils/calc.py)
対処
- ファイル側で定義されている正しい名前を確認して揃える
例:from myutils.calc import add_numbers
__init__.py
で__all__
を使っているなら、公開対象に含まれているか確認
循環importを避ける ファイルの分け方
ファイルAがファイルBをimport
し、同時にBがAをimport
すると、循環importになって初期化途中のモジュールを参照することになり、エラーになります。
再現コード
# a.py
from b import hello
def greet():
return "A says: " + hello()
# b.py
from a import greet
def hello():
return "Hello"
# main.py
import a
print(a.greet())
Traceback (most recent call last):
...
ImportError: cannot import name 'hello' from partially initialized module 'b' ...
対処の考え方
- 共通で必要な関数を新しいモジュール
common.py
に切り出す - 関数内ローカルimportにして依存の初期化順を回避する
# a.py
def greet():
from b import hello # 関数内で遅延importして循環を回避
return "A says: " + hello()
根本的には設計の見直しが最善です。
依存方向を一方向に揃えると安定します。
モジュール名の衝突に注意 同名ファイル(math.pyなど)
標準ライブラリやサードパーティのモジュール名を自作ファイルに付けると、意図せずそれを上書きしてしまうことがあります。
たとえばmath.py
という自作ファイルがあるとimport math
で自作ファイルが優先され、標準のmath
が使えなくなります。
再現と対処
- 自作
math.py
がある状態でimport math
すると、math.sqrt
などが見つからない - ファイル名を
my_math.py
のように変更する __pycache__
や.pyc
が残っていると古いキャッシュを参照することがあるため削除してから再実行する
# 誤ったレイアウト例 (同名衝突)
project/
├─ math.py # ← 標準ライブラリ math と同名。衝突の原因
└─ main.py
安全策として、標準ライブラリと同名のファイル名は避けましょう。
まとめ
別ファイルの関数を使う最小の手順は、関数を定義した.py
を用意し、使う側でimport
するだけです。
まずはimport モジュール名
で始め、名前の由来が明確なコードを心がけましょう。
フォルダ分けした場合はプロジェクトのルートからpython -m
で実行し、絶対importを徹底するとエラーを避けやすくなります。
エラーが出たら実行場所、ファイル名の綴り、パッケージ構成、そして同名衝突を落ち着いて確認してください。
from … import *は避け、必要なものを明示して読み込むのが、読みやすく壊れにくいPythonコードへの近道です。