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! ππ₯