-1

I'm writing a Flask restful API, through which an application will get some predictions. To prepare data for predictions I need to import a pickle full of objects. To unpickle it I need to import necessary class, stored in some directory in the project but not related to API.

Starting in the easiest way I tried to unpickle it in files using it, which produces less errors and then move imports one by one. But it still produced errors like:

Can't get attribute 'Doctor' on main' from 'C:\\Users\\

After hours of searching I finally added reference of class in the init file, from where I run the API just for tests in Postman and it worked:

import os
from src.classes.doctor import Doctor
from flask import Flask
from flask_bcrypt import Bcrypt
from flask_cors import CORS
from src.API.server.config import ProductionConfig

app = Flask(__name__)
CORS(app)

app.config.from_object(ProductionConfig)

bcrypt = Bcrypt(app)

from src.API.server.auth.views import auth_blueprint
app.register_blueprint(auth_blueprint)

if __name__ == "__main__":
    app.run(host='127.0.0.1', port=5002, debug=False)

Though I don't know why. Also, the import is shown as unused by Pycharm. Then I tried to create exactly the same test to it, through Unittest package, on the base that worked previously on other methods. It again produces the same error:

Can't get attribute 'Doctor' on main' from 'C:\\Users\\

I tried to import it in the BaseTestCase, but it didn't work.

This will also occur more times in the future. I would also want to import all of these references only once on API startup. Where should they be referenced, so it is always loaded properly and does not create circular imports? Why this fix works for Postman? Why it didn't work for tests?

Manaslu
  • 228
  • 1
  • 13

1 Answers1

1

Where should they be referenced, so it is always loaded properly and does not create circular imports?

Referencing in flask can be a bit tricky. I guess that you have used relative imports. But the app is run relative to the path of app.py (or whatever the name of your main file).

It is a good strategy to use only absolute imports. I would try to import only necessary things in your main file. Otherwise, it will be confusing when your app gets more complex.

Why it didn't work for tests?

Your tests are run from a different path than your main app. So it cannot find your imports. The best way to fix this is to add the neccessary paths to the runtime environment in the test file.

above_c_level
  • 3,579
  • 3
  • 22
  • 37
  • Thanks to your links I found what the problem is. The import must appear in __ main __ for some reason. I don't understand why my workaround works and how to fix this yet, but it's definitely not connected to flask in any way, but to unittest itself, which changes __ main __ to some build-in script. Hence, my question is wrong itself. In few hours I'm closing it, and, if I won't solve it, open correct one. – Manaslu Mar 24 '20 at 13:47
  • I forgot to mention one thing: do you have a __init__.py file in all folders? Otherwise pytest will not find it (if you are using pytest at all). – above_c_level Mar 24 '20 at 14:26
  • no, I use only unittest and flask_testing, but I have __ init __.py almost everywhere, so it's probably not the case – Manaslu Mar 24 '20 at 18:54