102
votes

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?

11
So now you have an app kicking off threads (which are difficult enough to debug themselves) and now you're going to suppress logging on top of that? Eesh, sounds like the opposite of what I'd do.. The more verbose your logging the better (obviously as long as it's relevant ;)). - Demian Brecht
@DemianBrecht The thing is, the logs are send to stderr but they are just logging each HTTP transaction, kinda irrelevant for me... - ATOzTOA

11 Answers

147
votes

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()
15
votes

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
13
votes

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.

11
votes

@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.

9
votes

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)
8
votes

To suppress Serving Flask app ...:

os.environ['WERKZEUG_RUN_MAIN'] = 'true'
app.run()
7
votes

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:

6
votes

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

2
votes

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"]},
    },
}
-1
votes

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

-3
votes

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