MeWrite Docs

ImportError: cannot import name 'X' from partially initialized module

Pythonで循環インポートが発生した場合のエラー

概要

ImportError: cannot import name 'X' from partially initialized module は、Pythonで2つ以上のモジュールが互いにインポートし合う循環インポートが発生した場合に発生するエラーです。

エラーメッセージ

ImportError: cannot import name 'function_b' from partially initialized module 'module_b' (most likely due to a circular import)
ImportError: cannot import name 'ClassA' from 'module_a'

原因

循環インポートの例

1
2
3
4
5
# module_a.py
from module_b import function_b

def function_a():
    return function_b()
1
2
3
4
5
# module_b.py
from module_a import function_a  # 循環インポート!

def function_b():
    return function_a()

解決策

1. インポートを関数内に移動

1
2
3
4
# module_a.py
def function_a():
    from module_b import function_b  # 遅延インポート
    return function_b()

2. モジュール全体をインポート

1
2
3
4
5
# module_a.py
import module_b

def function_a():
    return module_b.function_b()

3. 共通モジュールに切り出し

1
2
3
4
5
6
7
8
9
# common.py(新規作成)
def shared_function():
    pass

# module_a.py
from common import shared_function

# module_b.py
from common import shared_function

4. TYPE_CHECKINGで型ヒント用インポート

1
2
3
4
5
6
7
8
9
from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from module_b import ClassB  # 型チェック時のみインポート

class ClassA:
    def method(self, b: 'ClassB') -> None:
        pass

5. 構造を見直す

# Before: 循環依存
module_a <-> module_b

# After: 依存関係を整理
common
  ↑     ↑
module_a  module_b

6. importlibで動的インポート

1
2
3
4
5
import importlib

def get_function_b():
    module_b = importlib.import_module('module_b')
    return module_b.function_b

7. init.pyでの注意

1
2
3
4
5
6
7
# package/__init__.py
# すべてのモジュールを一度にインポートしない
# from .module_a import *
# from .module_b import *

# 必要に応じて個別にインポート
from .module_a import function_a

循環インポートの検出

1
2
3
4
5
6
# pycycleで検出
pip install pycycle
pycycle --here

# importlabで可視化
pip install importlab

設計パターン

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 依存性注入パターン
class ServiceA:
    def __init__(self, service_b=None):
        self.service_b = service_b

    def set_service_b(self, service_b):
        self.service_b = service_b

class ServiceB:
    def __init__(self, service_a=None):
        self.service_a = service_a

# メインモジュールで組み立て
a = ServiceA()
b = ServiceB(a)
a.set_service_b(b)

関連エラー

関連エラー

Python の他のエラー

最終更新: 2025-12-17