I am learning Flask. I found example with follow code
__init__.py:
from flask import Flask
app = Flask(__name__)
from app import views
view.py:
from app import app
#app.route('/')
def index():
return "hello world"
and run.py (on top level):
from app import app
app.run()
I can't understand why I can't move from app import views to the top. If I do so I am getting error:
> run.py
Traceback (most recent call last):
File "F:\app1\run.py", line 1, in <module>
from app import app
File "F:\app1\app\__init__.py", line 2, in <module>
from app import views
File "F:\app1\app\views.py", line 1, in <module>
from app import app
ImportError: cannot import name 'app'
Python is interpreted language. When it comes to one line it try to execute it. And that is why you cannot import views before defining app.
Working version of __init__.py
app = Flask(__name__)
from app import views # it will "execute: views.py"
# views.py - indenting for better understanding
from app import app # App is defined here and it can be imported
Not working version of __init__.py
from app import vies # it will execute vies.py"
# vies.py - indenting for better understanding
from app import app # Exception - app doesn't exist here
app = Flask(__name__)
You need to be really careful with python imports.
In run.py file line
from app import app
means "from package app (folder with __init__.py file, F:\app1\app in your case, import object app", and in __init__.py file line
app = Flask(__name__)
creates an application object. Main confusion caused by your application name - app - which coincides with application object name.
If you move line
from app import views
above
app = Flask(__name__)
from app import app in view.py will raise ImportError, because object app from app package not defined yet.
Related
I am trying to learn from a very helpful tutorial
https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login
on how to use flask_login.
My question: The complete tutorial works fine for me on my local PC, however I run into problems when trying to get this running on pythonanywhere.
The error seems ot be related to relative imports. In the best case, I want to come up with some code which runs both locally on my machine and on pythonanywhere.
For a minimal example, the project structure is as follows:
└── flask_auth_app
└── project
├── __init__.py
├── auth.py
├── main.py
with the files
__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret-key-goes-here'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db.init_app(app)
# blueprint for auth routes in our app
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
# blueprint for non-auth parts of app
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
auth.py
from flask import Blueprint
from . import db
auth = Blueprint('auth', __name__)
#auth.route('/login')
def login():
return 'Login'
#auth.route('/signup')
def signup():
return 'Signup'
#auth.route('/logout')
def logout():
return 'Logout'
main.py
from flask import Blueprint
from . import db
main = Blueprint('main', __name__)
#main.route('/')
def index():
return 'Index'
#main.route('/profile')
def profile():
return 'Profile'
To execute this on my local PC, I create an environment variable
set FLASK_APP=project
and run flask from the flask_auth_app directory
flask run
and everything runs fine.
I have now transferred the files to pythonanywhere and use the following configuration there:
source code: /home/grammaster/flask_auth_app
working directory: /home/grammaster/flask_auth_app
WSGI configuration file
# This file contains the WSGI configuration required to serve up your
# web application at http://<your-username>.pythonanywhere.com/
# It works by setting the variable 'application' to a WSGI handler of some
# description.
#
# The below has been auto-generated for your Flask project
import sys
# add your project directory to the sys.path
project_home = '/home/grammaster/flask_auth_app/project'
if project_home not in sys.path:
sys.path = [project_home] + sys.path
# import flask app but need to call it "application" for WSGI to work
from project import app as application # noqa
The resulting error message is
2021-08-13 05:58:26,704: Error running WSGI application
2021-08-13 05:58:26,706: ImportError: cannot import name 'app' from 'project' (/home/grammaster/flask_auth_app/./project/__init__.py)
2021-08-13 05:58:26,706: File "/var/www/grammaster_pythonanywhere_com_wsgi.py", line 16, in <module>
2021-08-13 05:58:26,707: from project import app as application # noqa
If I change the settings to
source code: /home/grammaster/flask_auth_app/project
working directory: /home/grammaster/flask_auth_app/project
and use
from main import app as application # noqa
the resulting error is
2021-08-13 06:10:53,086: Error running WSGI application
2021-08-13 06:10:53,089: ImportError: attempted relative import with no known parent package
2021-08-13 06:10:53,089: File "/var/www/grammaster_pythonanywhere_com_wsgi.py", line 16, in <module>
2021-08-13 06:10:53,089: from main import app as application # noqa
2021-08-13 06:10:53,089:
2021-08-13 06:10:53,089: File "/home/grammaster/flask_auth_app/project/main.py", line 2, in <module>
2021-08-13 06:10:53,089: from . import db
I am sure that the problem is rather trivial, but I seem to lack some basic understanding of relative imports on pythonanywhere and a flask server in general.
I have finally found the solution of getting the above example working with relative imports and on pythonanywhere. The problem was originating from wrong paths in the WSGI configuration file.
For the example and the paths above, the correct WSGI configuration file is
# This file contains the WSGI configuration required to serve up your
# web application at http://<your-username>.pythonanywhere.com/
# It works by setting the variable 'application' to a WSGI handler of some
# description.
#
# The below has been auto-generated for your Flask project
import sys
# add your project directory to the sys.path
project_home = '/home/grammaster/flask_auth_app'
if project_home not in sys.path:
sys.path = [project_home] + sys.path
# import flask app but need to call it "application" for WSGI to work
from project import create_app
application = create_app()
I'm trying to setup a flask application which runs on Python 3.7.x. I've referenced many tutorials online but can't seem to resolve this ModuleNotFoundError and none of the stackoverflow questions are related.
Below is my project structure:
project/
app/
__init__.py
api.py
conf.py
models.py
schema.py
orders-mgmt.toml
requirements.txt
README.md
# app/__init__.py
from flask import Flask
from flask_restful import Api
from app.conf import load_from_toml
import logging
import os.path
if os.path.isfile('/opt/project/orders-mgmt.toml'):
config = load_from_toml('/opt/project/orders-mgmt.toml')
else:
config = load_from_toml()
app = Flask(__name__)
api = Api(app)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = config['mysql']['db_uri']
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
'pool_recycle': 3000,
'pool_pre_ping': True,
}
# app/api.py
from flask import jsonify
from flask_restful import Resource
from flask_sqlalchemy import SQLAlchemy
from app import app, api, config #ERROR here
from app.models import Request
from app.schema import RequestSchema
db = SQLAlchemy(app)
class TestGet(Resource):
def get(self):
return 'okay'
api.add_resource(TestGet, '/')
if __name__ == '__main__':
app.run(debug=True, host='localhost', port=5000)
I'm getting the ModuleNotFoundError in app/api.py line from app import app, api, config when I run python app/api.py:
$ python app/api.py
Traceback (most recent call last):
File "app/api.py", line 4, in <module>
from app import app, api, config
ModuleNotFoundError: No module named 'app'
May I know what is the issue here with my flask application?
You have circular dependency issue
Your app will not work in such files structure
Remove logic from init module to another one OR you'll need to remove all absolute imports(imports for your own modules) and replace them with relative
for __init__ module
replace this line:
from app.conf import load_from_toml
with
from .conf import load_from_toml
for app module
replace these lines:
from app import app, api, config #ERROR here
from app.models import Request
from app.schema import RequestSchema
with
from . import app, api, config
from .models import Request
from .schema import RequestSchema
Trying to run the tutorial here: http://flask-sqlalchemy.pocoo.org/2.1/quickstart/ using my app
I have looked at the circular imports problem but I don't think that's it. I'm an absolute beginner to python and flask (and sqlalchemy). My app currently runs, but the database part doesn't
This is the current setup:
mysite
|- __init__.py
|- flask_app.py
|- models.py
|- views.py
init.py
from flask import Flask
app = Flask(__name__)
flask_app.py
from flask import Flask, request, url_for
import random
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:// -- database uri --'
... app continues here
models.py
from app import app
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
class Foo(db.Model):
... model continues here
views.py
from app import app,models
... views continue here, still not using anything from models
when I run from mysite import db in the python console I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'db'
Declare your db object in __init__.py. The stuff that is declared in __init__.py defines what can be imported under mysite/.
See: What is __init__.py for?
Also consider moving to the application factory pattern.
For example in __init__.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['DEBUG'] = True
... more application config ...
db.init_app(app)
return app
Then in flask_app.py:
from mysite import create_app, db
app = create_app()
if __name__ == '__main__':
app.run()
I point this out because you instantiate the app object twice in the code you've shown. Which is definitely wrong.
I had a problem with a circular import, so I moved my blueprint import below my app definition. However, I'm still having an import error.
Traceback (most recent call last):
File "/Applications/PyCharm CE.app/Contents/helpers/pydev/pydevd.py", line 2217, in <module>
globals = debugger.run(setup['file'], None, None)
File "/Applications/PyCharm CE.app/Contents/helpers/pydev/pydevd.py", line 1643, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/Users/benjamin/Documents/Projects/website/server/app/app.py", line 15, in <module>
from views import site
File "/Users/benjamin/Documents/Projects/website/server/app/views.py", line 2, in <module>
from models import User
File "/Users/benjamin/Documents/Projects/website/server/app/models.py", line 3, in <module>
from database_setup import db
File "/Users/benjamin/Documents/Projects/website/server/app/database_setup.py", line 1, in <module>
from app import app
File "/Users/benjamin/Documents/Projects/website/server/app/app.py", line 15, in <module>
from views import site
ImportError: cannot import name site
If I move the blueprint import and registration to if __name__ == '__main__':, the problem goes away, but I'm not sure if this is a good idea.
if __name__ == '__main__':
from views import site
app.register_blueprint(site)
app.run()
Is this the right way to solve the problem, or is there another solution?
original app.py without __main__ "fix":
from flask import Flask
app = Flask(__name__)
from views import site
app.register_blueprint(site)
if __name__ == '__main__':
app.debug = True
app.run()
views.py:
from flask import Blueprint, render_template
site = Blueprint('site', __name__, template_folder='templates', static_folder='static')
#site.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
database_setup.py:
from app import app
from flask_mongoengine import MongoEngine
app.config['MONGODB_SETTINGS'] = {'db': 'mst_website'}
db = MongoEngine(app)
models.py:
from database_setup import db
class User(db.Document):
# ...
My file structure is:
/server
|-- requirements.txt
|-- env/ (virtual environment)
|-- app/ (my main app folder)
|-- static/
|-- templates/
|-- __init__.py
|-- app.py
|-- database_setup.py
|-- models.py
|-- views.py
You have a circular import in your code. Based on the traceback:
app.py does from views import site
views.py does from models import User
models.py does from database_setup import db
database_setup.py does from app import app
app.py does from views import site
Based on these order of events, the app.py you've posted isn't the one that's actually causing your problem. Right now, app hasn't been defined before views is imported, so when further down the chain it tries to get app, it's not available yet.
You need to restructure your project so that everything that depends on app is imported after app is defined. From your question, it seems like you think you did, but perhaps there's still an import written above app that you missed.
Probably unrelated, but you are currently using "relative" imports, which are discouraged. Rather than doing from views import site, etc., you should do an absolute path: from app.views import site, or a relative path: from .views import site.
To answer the initial question of "is using __main__ to import blueprints a good idea?", it is not. The problem with that is that the __main__ guard is only executed when you run the module directly. When you go to deploy this using a real app server such as uWSGI or Gunicorn, none of your blueprints will be imported or registered.
I am working on an application, which looks similar in structure as
facebook/
__init__.py
feed/
__init__.py
models.py
business.py
views.py
chat/
__init__.py
models.py
business.py
views.py
My facebook.__init__.py is
from flask import Flask
app = Flask(__name__)
import feed.views
import chat.views
My facebook.runserver.py is
from . import app
app.run(debug=True)
My feed.views.py is
from .. import app
#app.route('/hello')
def hello():
return 'hello world'
My chat.views.py is
from .. import app
#app.route('/chat')
def chat():
return 'Let's chat'
When I try to run this application, as python runserver.py, I see error as
Traceback (most recent call last):
File "facebook/runserver.py", line 1, in <module>
from . import app
ValueError: Attempted relative import in non-package
How can I fix it?
put your runserver.py outside of the facebook folder and make its content as:
from facebook import app
app.run(debug=True)