Two-Bit Alchemist
Two-Bit Alchemist

Reputation: 18467

Testing Flask -- Avoiding Circular Import

I have been using Django for a while but decided to give Flask a try for my latest side project. Because I did not want my entire app in one file, I followed the documentation here to make my Flask app into a package. Crucially, these instructions introduce a sort of circular import:

Every Python programmer hates them, and yet we just added some: circular imports (That’s when two modules depend on each other. In this case views.py depends on __init__.py). Be advised that this is a bad idea in general but here it is actually fine. The reason for this is that we are not actually using the views in __init__.py and just ensuring the module is imported and we are doing that at the bottom of the file.

Indeed, this has not yet caused any problems in my app and my app will not function if I remove this line. However, my side project has gotten large enough I decided to try writing unit tests for it, using Flask-Testing. In all their documentation, they simply from package import app as normal, as in every submodule in my application. However, if I drop a tests.py in the main package directory and try this import, then try to run the tests, it fails with the circular import mentioned above:

File "/home/me/my_app/my_app/__init__.py", line 165, in <module>
  import views
File "/home/me/my_app/my_app/views.py", line 23, in <module>
  from my_app import app, db
ImportError: cannot import name app

In the documentation for Flask-Testing, as well as other places like the Mega-Tutorial section on Unit Testing, this import is done and seems to "just work". For me, however, this is the only time I have had a problem with this circular import. What have I missed?

Upvotes: 3

Views: 1395

Answers (1)

Michele d&#39;Amico
Michele d&#39;Amico

Reputation: 23721

As documented here your my_app/__init__.py should looks like:

from flask import Flask

app = Flask(__name__)
from my_app import views

Pay attention that app is defined before import views from your package. If you follow that rule you don't have any circular import issue.

Upvotes: 2

Related Questions