Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python, Flask print to console and log file simultaneously

I'm using python 3.7.3, with flask version 1.0.2.

When running my app.py file without the following imports:

import logging
logging.basicConfig(filename='api.log',level=logging.DEBUG)

Flask will display relevant debug information to console, such as POST/GET requests and which IP they came from.

As soon as DEBUG logging is enabled, I no longer receive this output. I have tried running my application in debug mode:

app.run(host='0.0.0.0', port=80, debug=True)

But this produces the same results. Is there a way to have both console output, and python logging enabled? This might sound like a silly request, but I would like to use the console for demonstration purposes, while having the log file present for troubleshooting.

like image 324
rjkunde Avatar asked Nov 21 '19 21:11

rjkunde


People also ask

Are Python flasks multithreaded?

As of Flask 1.0, flask server is multi-threaded by default. Each new request is handled in a new thread. This is a simple Flask application using default settings.

Does Python logging go to stdout?

It's Python core library's decision to log to stderr by default. It's common for logs to be redirected to stderr as stdout is usually reserved for a program's output/result: e.g. calls to print() are usually considered as proper output, and separated from logs.

How do I print a log in Python terminal?

Use logging Module to Print Log Message to a File in Python getLogger(name) method. There is a convention to use __name__ variable as the name of the logger. Once we have created a new logger, we should remember to log all our messages using the new logger.info() instead of the root's logging.info() method.


2 Answers

Found a solution:

import logging
from flask import Flask

app = Flask(__name__)

logger = logging.getLogger('werkzeug') # grabs underlying WSGI logger
handler = logging.FileHandler('test.log') # creates handler for the log file
logger.addHandler(handler) # adds handler to the werkzeug WSGI logger

@app.route("/")
def index():
    logger.info("Here's some info")
    return "Hello World"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

Other Examples:

# logs to console, and log file
logger.info("Some text for console and log file")

# prints exception, and logs to file
except Exception as ue:
        logger.error("Unexpected Error: malformed JSON in POST request, check key/value pair at: ")
        logger.error(ue)

Source: https://docstrings.wordpress.com/2014/04/19/flask-access-log-write-requests-to-file/

If link is broken:

You may be confused because adding a handler to Flask’s app.logger doesn’t catch the output you see in the console like:

127.0.0.1 - - [19/Apr/2014 18:51:26] "GET / HTTP/1.1" 200 -

This is because app.logger is for Flask and that output comes from the underlying WSGI module, Werkzeug.

To access Werkzeug’s logger we must call logging.getLogger() and give it the name Werkzeug uses. This allows us to log requests to an access log using the following:

logger = logging.getLogger('werkzeug')
handler = logging.FileHandler('access.log')
logger.addHandler(handler)

# Also add the handler to Flask's logger for cases
#  where Werkzeug isn't used as the underlying WSGI server.
#  This wasn't required in my case, but can be uncommented as needed
#  app.logger.addHandler(handler) 

You can of course add your own formatting and other handlers.

like image 57
rjkunde Avatar answered Oct 14 '22 00:10

rjkunde


Flask has a built-in logger that can be accessed using app.logger. It is just an instance of the standard library logging.Logger class which means that you are able to use it as you normally would the basic logger. The documentation for it is here.

To get the built-in logger to write to a file, you have to add a logging.FileHandler to the logger. Setting debug=True in app.run, starts the development server, but does not change the log level to debug. As such, you'll need to set the log level to logging.DEBUG manually.

Example:

import logging
from flask import Flask

app = Flask(__name__)

handler = logging.FileHandler("test.log")  # Create the file logger
app.logger.addHandler(handler)             # Add it to the built-in logger
app.logger.setLevel(logging.DEBUG)         # Set the log level to debug

@app.route("/")
def index():
    app.logger.error("Something has gone very wrong")
    app.logger.warning("You've been warned")
    app.logger.info("Here's some info")
    app.logger.debug("Meaningless debug information")
    return "Hello World"

app.run(host="127.0.0.1", port=8080)

If you then look at the log file, it should have all 4 lines printed out in it and the console will also have the lines.

like image 30
akrantz01 Avatar answered Oct 13 '22 23:10

akrantz01