Different methods of running flask app and setting environment - python

I have the following app which when I run using
flask run
seems to execute without error but when I perform python app.py gives me the following error:
➣ $ python app.py
Traceback (most recent call last):
File "app.py", line 14, in <module>
app.secret_key = os.environ['SECRET_KEY']
File "/Users/pkaramol/Workspace/second_flask/venv/bin/../lib/python3.7/os.py", line 678, in __getitem__
raise KeyError(key) from None
KeyError: 'SECRET_KEY'
#!/usr/bin/env python
import os
from flask import Flask
from flask_jwt import JWT, jwt_required
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy
import settings
from resources.item import Item, ItemList
app = Flask(__name__)
api = Api(app)
app.config.from_pyfile('settings.py')
app.secret_key = os.environ['SECRET_KEY']
db = SQLAlchemy(app)
if __name__ == "__main__":
print("Starting flask app...")
print(os.end['SECRET_KEY'])
db.create_all()
api.add_resource(Item, '/item/<string:name>')
api.add_resource(ItemList, '/items')
What is the difference in the two ways of running the flask app and why in the second case the environment is not rendered appropriately?
I am using python-dotenv to inject env vars from .env file
btw in the first case where the app starts without errors, I do not see the print statement I use for debug.
and if in the case of flask run the code below if __name__ == '__main__' is not called, how will I initialise my db by calling db.create_all()?

Replace app.secret_key assignment with arbitrary string.

Related

Python WSGI can't find local modules?

I am trying to get my Flask application to work with WSGI under Apache on RHEL 8. A flat file with no imports works fine, and the development server works fine, but WSGI returns module not found errors. This is my file strucuture:
/var/www/FLASKAPPS/myapp/
utility/
configuration.py
logging.py
__init__.py
Contents of init.py:
from flask import Flask, Response, request, abort
from flask_restful import Resource, Api, reqparse, inputs
from utility.configuration import Configuration
from utility.logger import Logger
app = Flask(__name__)
api = Api(app)
configuration = Configuration()
logger = Logger()
class Main(Resource):
#staticmethod
def get():
return {'message': 'Hello World.'}
api.add_resource(Main, '/')
if __name__ == "__main__":
app.run()
Running the Python test server works fine.
Accessing the server via WSGI on Apache gives the error:
File "/var/www/FLASKAPPS/myapp/__init__.py", line 6, in <module>
from utility.configuration import Configuration
No module named 'utility'
What do I need to do for WSGI to be able to see these modules?

Error: While importing 'application', an ImportError was raised

from flask import flask
app = Flask(__name__)
#app.route('/'):
def index():
return 'hrllo'
I keep getting
Serving Flask app 'application.py' (lazy loading)
Environment: development
Debug mode: on
Usage: flask run [OPTIONS]
Try 'flask run --help' for help.
Error: While importing 'application', an ImportError was raised.
Try:
from flask import Flask #changed "flask" to "Flask"
app = Flask(__name__)
#app.route('/') #removed ":"
def index():
return 'hello'
app.run() #added this line to run your application
from flask import Flask, correction in your first line.
Remove the colon at the end of the line marking the route.
Also, you should do app.run() at the end of the code snippet.

i've got a problem with flask using app.route()

i'm trying to create a web server with Flask python library but there is something wrong because it keeps giving me the error when i run the file.
here is the code:
from flask import Flask, app
app = Flask(__name__)
#app_route("/")
def main():
return('welcome to my flask page')
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port="8090")
here is the error:
Traceback (most recent call last):
File "c:\Users\User\Desktop\Simone\Simone\Js Course\Python Web Server\web server.py", line 5, in <module>
#app_route("/")
NameError: name 'app_route' is not defined
Help me please!!!
The app you're importing from flask isn't what you expect (it's a module within Flask that contains flask code). You need to create an instance of Flask, and apply the route to that.
from flask import Flask
app = Flask(__file__) # add this
#app.route('/') # and use app.route instead of app_route
...

PythonAnywhere and Flask app keep returning error code

trying to host my flask app (run.py) on PythonAnywhere. Have my virtualenv setup and all of my modules imported via pip. The flask app is stored at this location:
/home/goldsilvermonitor/GSM/run.py
Set up my WSGI file and it keeps giving my the error:
TypeError: 'module' object is not callable
My flask file look like this: (run.py)
from flask import Flask, flash, redirect, render_template, request, session, abort, url_for
app = Flask(__name__)
# ./Home Script:
#app.route("/")
#app.route("/index")
def index():
return render_template('index.html')
# ./Disclaimer Page:
#app.route("/disclaimer")
def disclaimer():
return render_template('disclaimer.html')
# ./data.xml:
app.route("/dataxml")
def dataxml():
return render_template('data.xml')
# ./404 Page
#app.errorhandler(404)
def page_not_found(e):
# 404 status set explicitly
return render_template('404.html'), 404
# FLask Debug Script:s
if __name__ == "__main__":
app.run(host="0.0.0.0", port='5000', debug=True)
And my WSGI file looks like this:
# +++++++++++ FLASK +++++++++++
# Flask works like any other WSGI-compatible framework, we just need
# to import the application. Often Flask apps are called "app" so we
# may need to rename it during the import:
#
#
import sys
#
## The "/home/goldsilvermonitor" below specifies your home
## directory -- the rest should be the directory you uploaded your Flask
## code to underneath the home directory. So if you just ran
## "git clone git#github.com/myusername/myproject.git"
## ...or uploaded files to the directory "myproject", then you should
## specify "/home/goldsilvermonitor/myproject"
path = '/home/goldsilvermonitor/GSM'
if path not in sys.path:
sys.path.append(path)
#
import run as application # noqa
#
# NB -- many Flask guides suggest you use a file called run.py; that's
# not necessary on PythonAnywhere. And you should make sure your code
# does *not* invoke the flask development server with app.run(), as it
# will prevent your wsgi file from working.
I have no idea what is causing this error. Have tried reuploading the files, redoing the WSGI config. But to no avail. If someone could help me then that would be great! Also should I remove the debug=true from the flask file before I go live?
You're trying to import a module (the file run.py) and then use it as an application; the application is the app object in that file, so in the WSGI file you should replace this:
import run as application # noqa
...with this:
from run import app as application # noqa

Use Flask's Click CLI with the app factory pattern

I define my Flask application using the app factory pattern. When using Flask-Script, I can pass the factory function to the Manager. I'd like to use Flask's built-in Click CLI instead. How do I use the factory with Click?
My current code uses Flask-Script. How do I do this with Click?
from flask import Flask
from flask_script import Manager, Shell
def create_app():
app = Flask(__name__)
...
return app
manager = Manager(create_app)
def make_shell_context():
return dict(app=app, db=db, User=User, Role=Role)
manager.add_command('shell', Shell(make_context=make_shell_context))
if __name__ == '__main__':
manager.run()
The flask command is a Click interface created with flask.cli.FlaskGroup. Create your own group and pass it the factory function. Use app.shell_context_processor to add objects to the shell.
from flask import Flask
from flask.cli import FlaskGroup
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(script_info=None):
app = Flask(__name__)
db.init_app(app)
...
#app.shell_context_processor
def shell_context():
return {'app': app, 'db': db}
return app
cli = FlaskGroup(create_app=create_app)
#cli.command
def custom_command():
pass
if __name__ == '__main__':
cli()
Run your file instead of the flask command. You'll get the Click interface using your factory.
FLASK_DEBUG=1 python app.py run
Ideally, create an entry point and install your package in your env. Then you can call the script as a command. Create a setup.py file with at least the following.
project/
app/
__init__.py
setup.py
from setuptools import setup, find_packages
setup(
name='my_app',
version='1.0.0',
packages=find_packages(),
entry_points={
'console_scripts': [
'app=app:cli',
],
},
)
pip install -e /path/to/project
FLASK_DEBUG=1 app run
Using your own CLI is less robust than the built-in flask command. Because your cli object is defined with your other code, a module-level error will cause the reloader to fail because it can no longer import the object. The flask command is separate from your project, so it's not affected by errors in your module.
Newly updated for Flask >= 2.1. See my other answer for Flask < 2.1.
In order to pass arguments to our app, we store them in script_info. And in order to do that, we create a custom Click interface using flask.cli.FlaskGroup.
However, passing script_info directly to app factories is deprecated in Flask 2, so we use
Click's get_current_context function to get the current context and then access script_info from that context.
manage.py
#!/usr/bin/env python
import click
import config
from click import get_current_context
from flask import Flask
from flask.cli import FlaskGroup, pass_script_info
def create_app(*args, **kwargs):
app = Flask(__name__)
ctx = get_current_context(silent=True)
if ctx:
script_info = ctx.obj
config_mode = script_info.config_mode
elif kwargs.get("config_mode"):
# Production server, e.g., gunincorn
# We don't have access to the current context, so must
# read kwargs instead.
config_mode = kwargs["config_mode"]
...
return app
#click.group(cls=FlaskGroup, create_app=create_app)
#click.option('-m', '--config-mode', default="Development")
#pass_script_info
def manager(script_info, config_mode):
script_info.config_mode = config_mode
...
if __name__ == "__main__":
manager()
Now you can run the dev server and set your desired config_mode by using either -m or --config-mode. Note, until Flask 2.1 drops you have to install Flask#aa13521d42bfdb
pip install git+https://github.com/pallets/flask.git#aa13521d42bfdb
python manage.py -m Production run
Production servers like gunincorn don't have access to the current context, so we pass what we need via kwargs.
gunicorn app:create_app\(config_mode=\'Production\'\) -w 3 -k gevent
In order to pass arguments to your app factory, you need to make use of script_info like so...
manage.py
#!/usr/bin/env python
import click
import config
from flask import Flask
from flask.cli import FlaskGroup, pass_script_info
def create_app(script_info):
app = Flask(__name__)
if script_info.config_mode:
obj = getattr(config, script_info.config_mode)
flask_config.from_object(obj)
...
return app
#click.group(cls=FlaskGroup, create_app=create_app)
#click.option('-m', '--config-mode', default="Development")
#pass_script_info
def manager(script_info, config_mode):
script_info.config_mode = config_mode
if __name__ == "__main__":
manager()
config.py
class Config(object):
TESTING = False
class Production(Config):
DATABASE_URI = 'mysql://user#localhost/foo'
class Development(Config):
DATABASE_URI = 'sqlite:///app.db'
class Testing(Config):
TESTING = True
DATABASE_URI = 'sqlite:///:memory:'
now in the command line you can do manage -m Production run (after either adding the entry_points to setup.py as #davidism mentioned, or running pip install manage.py).

Categories

Resources