Flask で circular import を避ける設計
Flask アプリケーションが大きくなると circular import(循環インポート)の問題に遭遇しやすい。モジュール A が B をインポートし、B が A をインポートすると、ImportError や AttributeError が発生する。
循環インポートが起きる典型例
# 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.py → views.py → app.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この構成なら、models や views から extensions.py の db をインポートしても循環は発生しない。











