0

I have the following application structure

/application
  app.py
  /decorators
    queryAccessory.py
  /auth
    __init__.py
    dao.py
    /controllers
      login.py
      register.py
    /models
      user.py
      get_user_response.py
  /tests
    __init__.py
    dao.py
    /controllers
      get_tests.py
    /models
      test.py
      get_tests_response.py

Blueprints are declared in the init.py files of the auth and tests packages.

from flask import Blueprint, request

tayyariAuth = Blueprint('tayyariAuth', __name__)
from auth.controllers import register
from auth.controllers import login

and in tests/init.py as

from flask import Blueprint, request

tayyariTests = Blueprint('tayyariTests', __name__)
from tests.controllers import get_tests

Both blueprints are registered in app.py. The problem is that the application does not start up when both init.py files have imports at the end. If I remove the last import lines from any 1 of the files, the application starts up and the registered blueprints work just fine. However, I get the following errors when the imports are there in both the init.py files

  File "app.py", line 8, in <module>
    from auth import tayyariAuth
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/auth/__init__.py", line 5, in <module>
    from auth.controllers import register 
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/auth/controllers/register.py", line 1, in <module>
    from auth import tayyariAuth, dao
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/auth/dao.py", line 1, in <module>
    from decorators.queryAccessor import Query
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/decorators/queryAccessor.py", line 1, in <module>
    from app import session
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/app.py", line 9, in <module>
    from tests import tayyariTests
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/tests/__init__.py", line 5, in <module>
    from tests.controllers import get_tests
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/tests/controllers/get_tests.py", line 1, in <module>
    from tests import tayyariTests, request, dao, TayyariEncoder
  File "/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/tests/dao.py", line 1, in <module>
    from decorators.queryAccessor import Query
ImportError: cannot import name 'Query' from 'decorators.queryAccessor' (/Users/anuragjoshi/Work/Tayyari/tayyari/tayyari-rest/decorators/queryAccessor.py)

Please help me understand what is going on here and how can I avoid this.

Thanks in advance.

rpanai
  • 12,515
  • 2
  • 42
  • 64
Anurag Joshi
  • 235
  • 1
  • 4
  • 17
  • My hunch is that this has something to do with registering multiple blueprints. Most examples that I see for larger applications show only 1 Blueprint being created and registered. Why is that so? I have another application in which I create blueprints in every module and there is no problem registering them. Please help. I am really stuck here. – Anurag Joshi Feb 19 '19 at 18:13

2 Answers2

0

It seems that the module decorators.queryAccessor is not in your python path. How are you doing the import of these blueprints? I usually have a factory method to create the app. In this method I have the imports to avoid circular references as follows:

def create_app():
    # Your code here
    ...
    from auth import tayyariAuth
    app.register_blueprint(tayyariAuth)
    from tests import tayyariTests
    app.register_blueprint(tayyariTests)
j2logo
  • 649
  • 4
  • 9
  • What is surprising is that there is no error in case I remove the imports at the end of 1 of the __init__.py files. If decorators.queryAccessor is not on the python path, then why should it work after removing the imports on one of the __init__.py files. – Anurag Joshi Feb 19 '19 at 16:30
  • It works because when you remove the imports, queryAccessor is not loaded. However, when imports are present, that module is referenced in any of that files. In this case, the interpreter tries to load the queryAccessor. – j2logo Feb 20 '19 at 15:32
0

The problem was because of a circular import as correctly pointed by @j2logo. However, the problem was not that decorators.queryAccessor was not on the python path.

The first line in the decorators.queryAccessor file was

from app import session

Inside my app.py I was calling imports to my packages that contained my blueprints.

from auth import tayyariAuth
from tests import test_blueprint

The init.py files in these packages are given in the question above. Because of the imports at the end of these init.py files, the login, register and get_tests modules were being imported that in turn imported the dao.py modules in their respective packages and these in turn imported decorators.queryAccessor.

So the circular path was

app.py -> auth -> auth/controllers/login.py -> auth/dao.py -> decorators.queryAccessor -> app.py

To break this I moved out my logic to initialise the db to another file db.py at the same level as app.py and created the required session variable by importing db.py before anything else. This created the required session object for the decorators.queryAccessor file and I imported session from db.py instead of app.py thus breaking the circular import.

Anurag Joshi
  • 235
  • 1
  • 4
  • 17