Flask-Script add_option method not working - python

Using flask-script's add_option method I'm trying to pass the name of a config file into my create_app() so I can configure from_pyfile() -- Flask Instance Folders
I used this gist to get me started.
manage.py
from fbone import create_app
app = create_app()
manager = Manager(app)
manager.add_option('-c', '--config', dest='config', required=False)
app.py
def create_app(config=None, app_name=None, blueprints=None):
"""Create a Flask app."""
print config
This is just a snippet of my create_app function but I'm starting the app like this:
$ python manage.py -c config/heroku.cfg runserver
None
/env/lib/python2.7/site-packages/flask_script/__init__.py:153: UserWarning: Options will be ignored.
* Running on http://127.0.0.1:5000/
* Restarting with reloader
None
As you can see, instead of printing config/heroku.cfg it prints None
I think this is because of the UserWarning from flask script but I can't find out why that's happening.

It turns out you are creating the flask object by calling create_app() (with the parens).
If you do
app=create_app
or
Manager(create_app)
then you should be able to use
add_option()

Related

make flask manage.py multithreaded

I'm using python, flask and and manage.py to create a backend-website with different routes, like /api/foo and /api/bar.
When accessing /api/foo the code should request data from /api/bar and process those data. But this (post-) request hangs endless, probably because the flask server is single threaded.
Currently the web-endpoint for /api/foo and /api/bar is started that way:
from flask_script import Manager
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)
if __name__ == '__main__':
manager.run()
So no app.run() is needed. This means, it's not possible to call something like app.run(threaded=True). But manager.run() does not support the threaded=True parameter.
How can I made the manage.py multi threaded?
btw: This is currently for development only. In production this app will use gunicorn or uWSGI later.

Deploy a flask app in using Cloudera Application

I have been using the following python 3 script in a CDSW session which run just fine as long as the session is not killed.
I am able to click on the top-right grid and select my app
hello.py
from flask import Flask
import os
app = Flask(__name__)
#app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host=os.getenv("CDSW_IP_ADDRESS"), port=int(os.getenv('CDSW_PUBLIC_PORT')))
I would like this app to run 24/7, so instead of using a Session or scheduling a job that never ends, I would like to create a CDSW Application so that it doesn't stop.
This is the settings on my application:
Logs:
from flask import Flask
import os
app = Flask(__name__)
#app.route('/')
def index():
return 'Web App with Python Flask!'
app.run(host=os.getenv("CDSW_IP_ADDRESS"), port=int(os.getenv('CDSW_PUBLIC_PORT')))
* Serving Flask app "__main__" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
OSError: [Errno 98] Address already in use
I tried to change the port from CDSW_PUBLIC_PORT to CDSW_APP_PORT but it ends up the same.
As it mentions here maybe you need to change this line of code
app.run(host=os.getenv("CDSW_IP_ADDRESS"), port=int(os.getenv('CDSW_PUBLIC_PORT')))
to this
app.run(host="127.0.0.1", port=int(os.environ['CDSW_APP_PORT']))
Hope it works!

Initialize Flask-SocketIO python app on heroku

I'm new to python, so this might be a dumb question, but I have the following issue:
I'm trying to deploy a Flask-SocketIO app to heroku, my app.py looks like this:
app = Flask(__name__)
socketio = SocketIO(app)
opt: Dict[Any, Any] = {}
.
.
#socketio.on('connect')
def joined():
test = json.dumps(opt)
emit('test', test)
.
.
if __name__ == '__main__':
opt = setup_args()
socketio.run(app)
My procfile looks like this:
web: gunicorn -k flask_sockets.worker app:app
If i run heroku local my server starts as expected, and I can establish a socket conection with my client, but my variable opt seems not to be filled. From what i've read in the docs, this is because the procfile does the socketio.run(app) for me, and my __main__ part is not getting executed.
I need to somehow trigger a method that initializes some variables in my app.py.
How can I achieve this?
Thanks
Is there a reason why you don't simply move opt = setup_args() out of the if statment, and move it, say, somewhere at the top of the file?

I don't need the run() method in a Flask application?

I have a Flask application setup on my linode with a directory structure like so:
|--------flask-test
|----------------app
|-----------------------static
|-----------------------templates
|-----------------------venv
|-----------------------__init__.py
|-----------------------main.py
my __init__.py is:
# __init__.py
from flask import Flask
from main import main
app = Flask(__name__)
app.register_blueprint(main)
app.run()
and main.py like so:
# main.py
from flask import Blueprint
main = Blueprint('main',__name__)
#main.route("/")
def hello():
return "Hello World!"
#main.route("/england/")
def england():
return "Hello England!"
If I run the app locally there are no issues. If I go to my server address in the web browser I get an internal server error. However if I remove the line: app.run from __init__.py it works fine. Why is this? Why do I not need the run method?
You should do
if __name__ == '__main__':
app.run()
The reason is that Apache or NGINX or some other web server loads your app directly on the server but app.run() runs flask's internal web-server so you can test your app.
It is a bit odd to have app.run() inside of the __init__.py file, normally it would be in a separate application script you run, where it would be written as:
if __name__ == '__main__':
app.run()
This way app.run() is only called when that script is executed as the application.
This is necessary because you do not want app.run() called when hosting under a WSGI server such as mod_wsgi or gunicorn. When using such WSGI servers, even if reusing the same script file as holder of the WSGI application entrypoint, __name__ wouldn't be set to __main__ but the basename of the script file. This ensures that app.run() isn't called where it is the separate WSGI server which is running the web server component.

Why is Flask application not creating any logs when hosted by Gunicorn?

I'm trying to add logging to a web application which uses Flask.
When hosted using the built-in server (i.e. python3 server.py), logging works. When hosted using Gunicorn, the log file is not created.
The simplest code which reproduces the problem is this one:
#!/usr/bin/env python
import logging
from flask import Flask
flaskApp = Flask(__name__)
#flaskApp.route('/')
def index():
flaskApp.logger.info('Log message')
print('Direct output')
return 'Hello World\n'
if __name__ == "__main__":
logHandler = logging.FileHandler('/var/log/demo/app.log')
logHandler.setLevel(logging.INFO)
flaskApp.logger.addHandler(logHandler)
flaskApp.logger.setLevel(logging.INFO)
flaskApp.run()
The application is called using:
gunicorn server:flaskApp -b :80 -w 4
--access-gfile /var/log/demo/access.log
--error-logfile /var/log/demo/error.log
When doing a request to the home page of the site, the following happens:
I receive the expected HTTP 200 "Hello World\n" in response.
There is a trace of the request in /var/log/demo/access.log.
/var/log/demo/error.log stays the same (there are just the boot events).
There is the "Direct output" line in the terminal.
There is no '/var/log/demo/app.log'. If I create the file prior to launching the application, the file is not modified.
Note that:
The directory /var/log/demo can be accessed (read, write, execute) by everyone, so this is not the permissions issue.
If I add StreamHandler as a second handler, there is still no trace of the "Log message" message neither in the terminal, nor in Gunicorn log files.
Gunicorn is installed using pip3 install gunicorn, so there shouldn't be any mismatch with Python versions.
What's happening?
This approach works for me: Import the Python logging module and add gunicorn's error handlers to it. Then your logger will log into the gunicorn error log file:
import logging
app = Flask(__name__)
gunicorn_error_logger = logging.getLogger('gunicorn.error')
app.logger.handlers.extend(gunicorn_error_logger.handlers)
app.logger.setLevel(logging.DEBUG)
app.logger.debug('this will show in the log')
My Gunicorn startup script is configured to output log entries to a file like so:
gunicorn main:app \
--workers 4 \
--bind 0.0.0.0:9000 \
--log-file /app/logs/gunicorn.log \
--log-level DEBUG \
--reload
When you use python3 server.py you are running the server3.py script.
When you use gunicorn server:flaskApp ... you are running the gunicorn startup script which then imports the module server and looks for the variable flaskApp in that module.
Since server.py is being imported the __name__ var will contain "server", not "__main__" and therefore you log handler setup code is not being run.
You could simply move the log handler setup code outside of the if __name__ == "__main__": stanza. But ensure that you keep flaskApp.run() in there since you do not want that to be run when gunicorn imports server.
More about what does if __name__ == “__main__”: do?
There are a couple of reasons behind this: Gunicorn has its own loggers, and it’s controlling log level through that mechanism. A fix for this would be to add app.logger.setLevel(logging.DEBUG).
But what’s the problem with this approach? Well, first off, that’s hard-coded into the application itself. Yes, we could refactor that out into an environment variable, but then we have two different log levels: one for the Flask application, but a totally separate one for Gunicorn, which is set through the --log-level parameter (values like “debug”, “info”, “warning”, “error”, and “critical”).
A great solution to solve this problem is the following snippet:
import logging
from flask import Flask, jsonify
app = Flask(__name__)
#app.route('/')
def default_route():
"""Default route"""
app.logger.debug('this is a DEBUG message')
app.logger.info('this is an INFO message')
app.logger.warning('this is a WARNING message')
app.logger.error('this is an ERROR message')
app.logger.critical('this is a CRITICAL message')
return jsonify('hello world')
if __name__ == '__main__':
app.run(host=0.0.0.0, port=8000, debug=True)
else:
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
Refrence: Code and Explanation is taken from here

Categories

Resources