ImportError: cannot import name 'User' from partially initialized module 'models' (most likely due to a circular import) は、2つ以上のファイルが互いに import し合っていて、読み込みの途中のファイルから名前を取り出そうとしたときのエラーです。 「循環インポート」と呼ばれます。

Python 3.13 ではメッセージが変わり、「circular import」と表示されなくなりました。 版によって、次のどれかが出ます。

Python 同じ循環インポートのメッセージ
3.10〜3.12 cannot import name 'User' from partially initialized module 'models' (most likely due to a circular import)
3.13 cannot import name 'User' from 'models' (consider renaming '.../models.py' if it has the same name as a library you intended to import)

3.13 のメッセージは「ファイル名がライブラリと同じでは」と案内しますが、自分で作った2つのファイルが import し合っているだけでも、この表示になりました。どちらの版でも、トレースバックで循環を見つけるのが確実です。

確認環境:Python 3.10・3.11・3.12・3.13、mypy(確認日 2026年10月11日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「cannot import nameの直し方|Pythonの循環インポート」

再現:models.py と services.py が互いに import

# models.py
from services import notify

class User:
    def __init__(self, name):
        self.name = name
    def register(self):
        notify(self)
# services.py
from models import User

def notify(user: User):
    print(f"{user.name} さんを登録しました")
# main.py
from models import User
User("佐藤").register()
Traceback (most recent call last):
  File ".../main.py", line 1, in <module>
    from models import User
  File ".../models.py", line 1, in <module>
    from services import notify
  File ".../services.py", line 1, in <module>
    from models import User
ImportError: cannot import name 'User' from 'models' (consider renaming '.../models.py' if it has the same name as a library you intended to import)

トレースバックで循環を見つける

トレースバックの File と from ... import を上から順に追うと、輪になっている箇所が分かります。

main.py      → from models import User       (models の読み込みを始める)
models.py    → from services import notify   (models の1行目で services へ)
services.py  → from models import User       (models に戻る。models はまだ1行目の途中)

models.py は1行目の途中なので、まだ class User が作られていません。 そこから User を取り出そうとしたため、失敗しました。メッセージの partially initialized module(初期化の途中のモジュール) は、この状態を指しています。

直し方1:モジュールごと import して、使うときに参照する

# services.py
import models                      # モジュールごと import する

def notify(user):
    print(f"{user.name} さんを登録しました")

def create(name):
    return models.User(name)       # 使うとき(関数の実行時)に参照する

from models import User(読み込んだ瞬間に User を取り出す)ではなく、import models にすると、読み込みの時点では名前を取り出さないので、循環していても止まりませんでした(佐藤 さんを登録しました)。関数が呼ばれるころには、models の読み込みが終わっています。

直し方2:関数の中で import する

# services.py
def create(name):
    from models import User        # 関数が呼ばれたときに import
    return User(name)

これも動きました。手軽ですが、import がファイルのあちこちに散るので、一時的な回避や、使う場所が1か所のときに向いています。

直し方3:共通の部分を別のファイルに分ける(根本的な直し方)

互いに使う部分(ここでは User)を、第3のファイルに移します。

entities.py   ← User(ほかを import しない)
services.py   ← from entities import User
models.py     ← from entities import User / from services import notify
# entities.py
class User:
    def __init__(self, name):
        self.name = name

依存の向きが一方向(entities ← services ← models)になり、循環が無くなりました。 ファイルの役割(データの定義・処理)を分けると、循環は起きにくくなります。

直し方4:型ヒントのためだけの import は TYPE_CHECKING

User を型ヒント(user: User)にしか使っていないなら、実行時には import しない書き方にできます。

# services.py
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:                  # 型チェックのときだけ import(実行時は import しない)
    from models import User

def notify(user: User) -> None:
    print(f"{user.name} さんを登録しました")

確認環境では、実行すると 佐藤 さんを登録しました と動き、mypy でも Success: no issues found でした。from __future__ import annotations で、型ヒントを実行時に評価しないようにしています。

直し方 向いている場面
1. import models で、使うときに参照 実行時に使うが、読み込み時には使わない
2. 関数の中で import 使う場所が1か所、一時的な回避
3. 共通部分を別ファイルに 根本的に直したい(おすすめ)
4. TYPE_CHECKING 型ヒントにしか使っていない

もう1つの原因:標準ライブラリと同じファイル名

(random.py という名前のファイルに from random import randint と書いて実行)
Python 3.10: ImportError: cannot import name 'randint' from partially initialized module 'random' (most likely due to a circular import) (.../random.py)
Python 3.13: ImportError: cannot import name 'randint' from 'random' (consider renaming '.../random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)

自分のファイル random.py が、標準ライブラリの random の代わりに読み込まれ、自分自身を import する形になりました。 3.10 では「circular import」と表示されるので、本当の循環と区別がつきません。json.py では AttributeError: ... module 'json' has no attribute 'dumps' になりました。

確認すること 方法
ファイル名が標準ライブラリ・使っているライブラリと同じでないか random.py・json.py・email.py・test.py・requests.py・pandas.py など
3.13 なら since it has the same name as the standard library module と表示される

ファイル名を変え、同じフォルダーにできた __pycache__ も消します。 Python 3.13 の改善点(What's New)でも、標準ライブラリと同じ名前のスクリプトが、よくある間違いとして挙げられています。

循環ではない cannot import name

ImportError: cannot import name 'b' from 'util' (.../util.py)

partially initialized も consider renaming も付かないなら、単に その名前がファイルに無いことが原因です(綴りの間違い、関数名の変更、ライブラリの版の違い)。ライブラリの場合は、使っている版でその名前が提供されているかを確かめます。

確認の手順(チェックリスト)

順番 確認すること 方法
1 メッセージの形 partially initialized(3.12 以前)・consider renaming(3.13)・どちらも無い
2 循環の場所 トレースバックの File と from ... import を順に追う
3 ファイル名 標準ライブラリ・ライブラリと同じ名前でないか
4 直す 共通部分を別ファイルに。急ぐなら import モジュール か関数の中で import
5 型ヒントだけなら TYPE_CHECKING
6 循環でないなら 名前の綴り・ライブラリの版

よくある質問

Q. Django・Flask でも出ますか。 A. 出ます。models と views、app と routes などが互いに import し合う形で起きやすくなります。直し方は同じで、共通部分を分けるか、文字列での参照(Django の ForeignKey("app.Model") など、フレームワークが用意している方法)を使います。

Q. import の順番を入れ替えると直ることがあります。 A. 読み込みの順番によっては、名前が作られたあとに取り出す形になり、たまたま動くことがあります。ファイルを1つ足しただけで再発するので、上の直し方で循環を無くすのが確実です。

まとめ

  • 2つ以上のファイルが互いに import し、読み込みの途中から名前を取り出したエラー
  • Python 3.13 では「circular import」と表示されない。consider renaming と出ても、循環の可能性がある
  • トレースバックの from ... import を追うと、輪になっている箇所が分かる
  • 根本は共通部分を別ファイルに。急ぐなら import モジュール か関数の中で import
  • 型ヒントだけなら TYPE_CHECKING
  • random.py など標準ライブラリと同じファイル名でも同じエラーになる

参考・出典

確認日はいずれも 2026年10月11日です。

  • Python ドキュメント「What's New In Python 3.13」(Improved error messages):https://docs.python.org/3/whatsnew/3.13.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「cannot import nameの直し方|Pythonの循環インポート」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?