いろは2986023 views
高校化学2913383 views
高校生物549842 views
教育148875 views
小学理科717236 views
数学講師2852771 views
Computer365120 views
高校日本史189857 views
高校物理158224 views
中学英語808712 views
Help
Tools

English

Flask で circular import を避ける設計

Flask アプリケーションが大きくなると circular import(循環インポート)の問題に遭遇しやすい。モジュール A が B をインポートし、B が A をインポートすると、ImportErrorAttributeError が発生する。

循環インポートが起きる典型例

# app.py
from flask import Flask
from views import main_bp  # views.py をインポート

app = Flask(__name__)
app.register_blueprint(main_bp)
# views.py
from flask import Blueprint
from app import app  # app.py をインポート → 循環

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
def index():
    return app.config['APP_NAME']  # app を使いたい

この構成では app.pyviews.pyapp.py の循環が発生する。

解決策 1: current_app を使う

app を直接インポートせず、current_app を使う。

# views.py
from flask import Blueprint, current_app

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
def index():
    return current_app.config['APP_NAME']  # リクエスト中は current_app が使える

解決策 2: アプリケーションファクトリパターン

app インスタンスを関数内で生成し、循環を避ける。

# app/__init__.py
from flask import Flask

def create_app():
    app = Flask(__name__)
    
    from app.views import main_bp  # 関数内でインポート
    app.register_blueprint(main_bp)
    
    return app
# app/views.py
from flask import Blueprint, current_app

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
def index():
    return current_app.config['APP_NAME']

解決策 3: 遅延インポート

必要になった時点でインポートする。

# models.py
def get_user_model():
    from app.models.user import User  # 関数内でインポート
    return User

推奨されるディレクトリ構成

app/
├── __init__.py      # create_app() を定義
├── extensions.py    # db, login_manager などを初期化(app なし)
├── models/
│   └── user.py
├── views/
│   └── main.py
└── config.py
# extensions.py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()  # app なしで初期化
# __init__.py
from flask import Flask
from app.extensions import db

def create_app():
    app = Flask(__name__)
    db.init_app(app)  # 後から app を渡す
    return app

この構成なら、modelsviews から extensions.pydb をインポートしても循環は発生しない。