Are you getting this frustrating error while running your Flask app?
ImportError: cannot import name 'app' from partially initialized module 'app' (most likely due to a circular import)
You're not alone! Circular imports are a common issue in Flask apps, and in this post, I'll show you exactly why this happens and give you modern solutions with real examples to fix it.
🔍 Understanding the Circular Import Error
A circular import happens when two or more modules depend on each other, creating an infinite loop.
🛑 Example of Circular Import Issue
❌ app.py
(Before - Problematic Code)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from backend.config import Config # 🚨 Circular Import Risk!
from backend.routes import routes
import backend.utils as utils
db = SQLAlchemy()
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
app.register_blueprint(routes)
with app.app_context():
utils.reset_database()
utils.initialize_db()
if __name__ == '__main__':
app.run(debug=True)
❌ backend/config.py
(Before - Problematic Code)
from app import app # 🚨 Circular Import Error Happens Here!
class Config:
SQLALCHEMY_DATABASE_URI = 'sqlite:///example.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
🔄 What’s Happening?
-
app.py
importsConfig
frombackend.config
-
backend/config.py
importsapp
fromapp.py
-
Flask hasn't finished initializing
app
, so the import is incomplete → Boom! Circular Import Error! 💥
✅ How to Fix Circular Imports in Flask? (Modern Solutions)
📌 Solution 1: Move the Import Inside a Function
Instead of importing app
at the top of backend/config.py
, import it only when needed.
✨ Fixed backend/config.py
class Config:
SQLALCHEMY_DATABASE_URI = 'sqlite:///example.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
✅ Now, config.py
is independent and doesn’t need app.py
.
📌 Solution 2: Use Flask’s App Factory Pattern (🔥 Recommended)
A better way to structure your Flask app is to use the App Factory Pattern, which ensures components are initialized properly.
✨ Updated app.py
from flask import Flask
from backend.config import Config
from backend.routes import routes
from backend.extensions import db # Import `db` from extensions
import backend.utils as utils
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app) # Initialize database
app.register_blueprint(routes)
with app.app_context():
utils.reset_database()
utils.initialize_db()
return app # ✅ Returns the app instance
if __name__ == '__main__':
app = create_app() # Create app dynamically
app.run(debug=True)
✨ Updated backend/config.py
class Config:
SQLALCHEMY_DATABASE_URI = 'sqlite:///example.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
✅ Now, config.py
no longer depends on app.py
, breaking the import loop.
📌 Solution 3: Separate Flask Extensions into a New File
Another clean way to structure your app is to move db = SQLAlchemy()
to a separate file.
✨ New backend/extensions.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() # Define the database instance separately
✨ Updated app.py
from flask import Flask
from backend.config import Config
from backend.routes import routes
from backend.extensions import db # Import `db` separately
import backend.utils as utils
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
app.register_blueprint(routes)
with app.app_context():
utils.reset_database()
utils.initialize_db()
return app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
✅ This keeps the database setup clean and prevents circular imports.
🚀 Bonus: Full Modern Flask App Structure
Here's a modern way to structure your Flask project:
/household-service-v2
│── app.py # App Factory
│── backend/
│ ├── __init__.py # Initialize the Flask app
│ ├── config.py # App configuration
│ ├── extensions.py # Database and extensions
│ ├── routes.py # API routes
│ ├── utils.py # Helper functions
│── venv/
💡 Why is this better?
-
🔥 Scalable – Easy to add new features without breaking imports.
-
✅ No Circular Imports – Each component is modular.
-
🛠️ Best Practices – Follow Flask's recommended App Factory approach.
🎯 Conclusion
Circular imports in Flask happen when files depend on each other in a loop.
✅ How to Fix It:
-
Move imports inside functions
-
Use the Flask App Factory Pattern (🔥 Best Solution)
-
Separate Flask extensions into a new file (
extensions.py
)
By following these best practices, you’ll build modular, scalable, and bug-free Flask applications! 🚀💡
💬 Got Questions?
Leave a comment below or share your thoughts! Happy coding! 🎉🔥