Cannot enable debug mode in production server in Flask [duplicate] - python

This question already has an answer here:
Why isn't Flask giving me an interactive debugger?
(1 answer)
Closed 4 years ago.
I'm trying to enable debug mode in browser as follows:
from werkzeug.debug import DebuggedApplication
application = Flask(__name__)
app = application
application = DebuggedApplication(app, True)
But it does not enable debug mode in my production server Apache under mod_wsgi.
Did I have something wrong? Also the export method doesn't work either.

The DebuggedApplication() middleware only works if an uncaught exception reaches it.
Flask, in production mode, catches all exceptions so these never reach the middleware.
You need to explicitly tell Flask to not catch all exceptions with:
PROPAGATE_EXCEPTIONS = True
in your configuration. From the relevant documenation:
PROPAGATE_EXCEPTIONS
Exceptions are re-raised rather than being handled by the app’s error handlers. If not set, this is implicitly true if TESTING or DEBUG is enabled.
You can set it on the app object before wrapping it in the DebuggedApplication middleware:
app = Flask(__name__)
app.config['PROPAGATE_EXCEPTIONS'] = True
app.wsgi_app = DebuggedApplication(app.wsgi_app, True)
Note that this only tells Flask to not catch all exceptions any more. You may also want to set other configuration options such as PRESERVE_CONTEXT_ON_EXCEPTION, or you could just enable debug mode with app.debug = True.

Related

Why cherrypy server logs error messages even though it seems to work?

I'm using cherrypy to start a server, that its computation engine is Apache Spark. It logs this weird result:
[06/Dec/2017:13:25:42] ENGINE Bus STARTING
INFO:cherrypy.error:[06/Dec/2017:13:25:42] ENGINE Bus STARTING
[06/Dec/2017:13:25:42] ENGINE Started monitor thread 'Autoreloader'.
INFO:cherrypy.error:[06/Dec/2017:13:25:42] ENGINE Started monitor thread 'Autoreloader'.
[06/Dec/2017:13:25:42] ENGINE Serving on http://0.0.0.0:5432
INFO:cherrypy.error:[06/Dec/2017:13:25:42] ENGINE Serving on http://0.0.0.0:5432
[06/Dec/2017:13:25:42] ENGINE Bus STARTED
INFO:cherrypy.error:[06/Dec/2017:13:25:42] ENGINE Bus STARTED
My question is, what is this INFO:cherrypy.error: it logs?
This is how I run the server:
def run_server(app):
# Enable WSGI access logging via Paste
app_logged = TransLogger(app)
# Mount the WSGI callable object (app) on the root directory
cherrypy.tree.graft(app_logged, '/')
# Set the configuration of the web server
cherrypy.config.update({
'engine.autoreload.on': True,
'log.screen': True,
'server.socket_port': 5432,
'server.socket_host': '0.0.0.0'
})
# Start the CherryPy WSGI web server
cherrypy.engine.start()
cherrypy.engine.block()
There's absolutely nothing wrong with what you're seeing in the log file. I see the same bus and serving statements when I run Cherrypy. I guess Cherrypy haven't really used the term 'error' too effectively there, like some people call the HTTP status codes 'error codes', when in fact code 200 means everything is all good.
I think for your case, the listeners (for activities logging) are essentially wired with the function _buslog in cherrypy/__ init__.py , and they eventually will call the function error() in cherrypy/_cplogging.py
and according to the description there:
""" Write the given ``msg`` to the error log.
This is not just for errors! Applications may call this at any time
to log application-specific information.
If ``traceback`` is True, the traceback of the current exception
(if any) will be appended to ``msg``.
"""
So , yeah, this is not just for errors...

How to use app.debug in Flask app deployed on Azure?

I've created a simple Flask app using Azure, which I git cloned and modified to enable debug mode - my __init.py__ now looks like:
from flask import Flask
app = Flask(__name__)
app.debug = True
import FlaskWebProject1.views
And then made it throw a server error, in the project's views.py:
def bad_method():
return 1/0
#app.route('/')
def home():
"""Renders the home page."""
a = bad_method()
return render_template(...) # Never gets here
When I run this locally using the development server (runserver.py), I get a useful stacktrace in the console and also in the browser - this is what I want.
When I push the code up to Azure and visit the deployed site I get a plain The page cannot be displayed because an internal server error has occurred. 500 Error, with no stacktrace shown in the browser.
Is there a way that I can enable the same debug mode while developing that I have locally when my code is deployed in Azure? The stack trace in a log would be OK, but in the browser would be far better.
EDIT: I've modified my views to pass through app.debug to a template, and it shows as True. So this must be Azure somehow hiding the stack trace?

error tracking for server on flask [duplicate]

This question already has answers here:
Flask application traceback doesn't show up in server log
(4 answers)
Closed 5 years ago.
I have a server written on flask and I need to do error tracking (name of error, what caused the error, name of file and line with error).
How should I do it?
I'll appreciate any help.
enable the flask debugger, by setting debug to True for your flask app.
app = Flask(__name__)
app.config['DEBUG'] = True
As you shouldn't enable debug for a production server, you can create a logging
handler as follows: http://flask.pocoo.org/docs/0.12/errorhandling/

unable to load configuration from uwsgi

I have below setup in my Python application
server.py
from bots.flask_app import app
from bots.flask_app.api import api
from bots.flask_app.public import public
from bots import db
from bots.commons.helpers.flask.json.serializer import make_alternative_encoder
from flask_debugtoolbar import DebugToolbarExtension
import logging
import bots.commons.managers.configuration as ConfigurationManager
logger = logging.getLogger()
#######
# Public functions
#######
def setup_db_and_app():
# Flask application bootstrap
config = ConfigurationManager.get_flask_rest_config()
app.config.update(config)
logger.debug('Flask configuration object: %s', app.config)
# MongoDB connection initialization
db.init_app(app)
# Debug toolbar enabled only if Flask in debug mode
if ConfigurationManager.get_raw_flask_rest_config()['flask']['debug']:
DebugToolbarExtension(app)
# Replace the serializer with the custom one (for ObjectId and DateTime serialization)
app.json_encoder = make_alternative_encoder(app.json_encoder)
# Register the components
app.register_blueprint(api)
app.register_blueprint(public)
def start_server():
setup_db_and_app()
logger.debug('Registered routes: %s', app.url_map)
app.run(host='0.0.0.0')
main.py
import bots.flask_app.server as FlaskApp
import bots.commons.managers.log as LogManager
# Logging initialization
LogManager.init_logging()
# Defined in server.py
FlaskApp.start_server()
I am trying to see whether this applicator can bed served by uwsgi as below
uwsgi --socket 0.0.0.0:8080 --protocol=http -w main
The output is as follows
INFO:werkzeug: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
INFO:werkzeug: * Restarting with stat
unable to load configuration from uwsgi
My questions
1. Where can I find the configurations which are causing this issue?
2. Can main.py be defined as a callable and used as a parameter for -w?
This is an app which is already written by someone and I am trying make this application served through uwsgi.
Any suggestions would be helpful
Thanks
I had the 'unable to load configuration from uwsgi' error too. According to flask uwsgi docs:
Please make sure in advance that any app.run() calls you might have in your application file are inside an if __name__ == '__main__': block or moved to a separate file. Just make sure it’s not called because this will always start a local WSGI server which we do not want if we deploy that application to uWSGI.
I move app.run() to if __name__ == '__main__':, and the problem solved. Maybe you can try to put FlaskApp.start_server() under if __name__ == '__main__':.
I'm a bit late to the party, I've encountered this error when I forgot to remove debug=True from app.run(). It makes sense that you can't run the debug server with uwsgi.

Disable console messages in Flask server

I have a Flask server running in standalone mode (using app.run()). But, I don't want any messages in the console, like
127.0.0.1 - - [15/Feb/2013 10:52:22] "GET /index.html HTTP/1.1" 200 -
...
How do I disable verbose mode?
You can set level of the Werkzeug logger to ERROR, in that case only errors are logged:
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
Here is a fully working example tested on OSX, Python 2.7.5, Flask 0.10.0:
from flask import Flask
app = Flask(__name__)
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
This solution provides you a way to get your own prints and stack traces but without information level logs from flask suck as 127.0.0.1 - - [15/Feb/2013 10:52:22] "GET /index.html HTTP/1.1" 200
from flask import Flask
import logging
app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.disabled = True
None of the other answers worked correctly for me, but I found a solution based off Peter's comment. Flask apparently no longer uses logging for logging, and has switched to the click package. By overriding click.echo and click.secho I eliminated Flask's startup message from app.run().
import logging
import click
from flask import Flask
app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
def secho(text, file=None, nl=None, err=None, color=None, **styles):
pass
def echo(text, file=None, nl=None, err=None, color=None, **styles):
pass
click.echo = echo
click.secho = secho
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
Between setting the logging level to ERROR and overriding the click methods with empty functions, all non-error log output should be prevented.
To suppress Serving Flask app ...:
os.environ['WERKZEUG_RUN_MAIN'] = 'true'
app.run()
In case you are using WSGI server , please set the log to None
gevent_server = gevent.pywsgi.WSGIServer(("0.0.0.0", 8080), app, log=None)
#Drewes solution works most of the time, but in some cases, I still tend to get werkzeug logs. If you really don't want to see any of them, I suggest you disabling it like that.
from flask import Flask
import logging
app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.disabled = True
app.logger.disabled = True
For me it failed when abort(500) was raised.
Late answer but I found a way to suppress EACH AND EVERY CONSOLE MESSAGE (including the ones displayed during an abort(...) error).
import os
import logging
logging.getLogger('werkzeug').disabled = True
os.environ['WERKZEUG_RUN_MAIN'] = 'true'
This is basically a combination of the answers given by Slava V and Tom Wojcik
Another reason you may want to change the logging output is for tests, and redirect the server logs to a log file.
I couldn't get the suggestion above to work either, it looks like loggers are setup as part of the app starting. I was able to get it working by changing the log levels after starting the app:
... (in setUpClass)
server = Thread(target=lambda: app.run(host=hostname, port=port, threaded=True))
server.daemon = True
server.start()
wait_for_boot(hostname, port) # curls a health check endpoint
log_names = ['werkzeug']
app_logs = map(lambda logname: logging.getLogger(logname), log_names)
file_handler = logging.FileHandler('log/app.test.log', 'w')
for app_log in app_logs:
for hdlr in app_log.handlers[:]: # remove all old handlers
app_log.removeHandler(hdlr)
app_log.addHandler(file_handler)
Unfortunately the * Running on localhost:9151 and the first health check is still printed to standard out, but when running lots of tests it cleans up the output a ton.
"So why log_names?", you ask. In my case there were some extra logs I needed to get rid of. I was able to find which loggers to add to log_names via:
from flask import Flask
app = Flask(__name__)
import logging
print(logging.Logger.manager.loggerDict)
Side note: It would be nice if there was a flaskapp.getLogger() or something so this was more robust across versions. Any ideas?
Some more key words: flask test log remove stdout output
thanks to:
http://code.activestate.com/lists/python-list/621740/ and
How to change filehandle with Python logging on the fly with different classes and imports
I spent absolute ages trying to get rid of these response logs with all the different solutions, but as it turns out it wasn't Flask / Werkzeug but Gunicorn access logs dumped on stderr...
The solution was replacing the default access log handler with NullHandler by adding this block in the Gunicorn config file:
logconfig_dict = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {"class": "logging.StreamHandler", "level": "INFO"},
"null": {"class": "logging.NullHandler"},
},
"loggers": {
"gunicorn.error": {"level": "INFO", "propagate": False, "handlers": ["console"]},
"gunicorn.access": {"level": "INFO", "propagate": False, "handlers": ["null"]},
},
}
somehow none of the above options, including .disabled = True, worked for me.
The following did the trick though:
logging.getLogger('werkzeug').setLevel(logging.CRITICAL)
Using the latest versions as of November 2021 under Python 3.7.3:
pip3 list | grep -E "(connexion|Flask|Werkzeug)"
connexion2 2.10.0
Flask 2.0.2
Werkzeug 2.0.2
Here's the answer to disable all logging, including on werkzeug version 2.1.0 and newer:
import flask.cli
flask.cli.show_server_banner = lambda *args: None
import logging
logging.getLogger("werkzeug").disabled = True
My current workaround to silence Flask as of 2022-10.
It disables the logging and the startup banner:
class WSServer:
...
#staticmethod
def _disabled_server_banner(*args, **kwargs):
"""
Mock for the show_server_banner method to suppress spam to stdout
"""
pass
def _run_server(self):
"""
Winds-up the server.
"""
# disable general logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.CRITICAL)
# disable start-up banner
from flask import cli
if hasattr(cli, "show_server_banner"):
cli.show_server_banner = self._disabled_server_banner
...
A brute force way to do it if you really don't want anything to log into the console beside print() statements is to logging.basicConfig(level=logging.FATAL). This would disable all logs that are of status under fatal. It would not disable printing but yeah, just a thought :/
EDIT:
I realized it would be selfish of me not to put a link to the documentation I used :)
https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
The first point: In according to official Flask documentation, you shouldn't run Flask application using app.run(). The best solution is using uwsgi, so you can disable default flask logs using command "--disable-logging"
For example:
uwsgi --socket 0.0.0.0:8001 --disable-logging --protocol=http -w app:app

Categories