Philip
Philip

Reputation: 1931

How to log from separate module in Flask

I have a simple Flask app like this:

from flask import Flask
import util

APP = Flask("app")
APP.debug = True

@APP.route('/', methods=['GET'])
def index():
    APP.logger.info("info message from index")
    util.test()
    return "hello world"

if __name__ == '__main__':
    APP.run()

Where the util module is:

import logging

logger = logging.getLogger(__name__)

def test():
    logger.info("info message from util")

When I run only "info message from index" appears in the console.

What is the simplest way to get the two logging messages to print to the console together, and to also both print to a log file together.

I've tried various approaches and none have worked for me. In particular the util one never shows up.

Upvotes: 13

Views: 6909

Answers (2)

davidism
davidism

Reputation: 127410

The logger in util doesn't generate output because Python logging is set to log warnings and higher by default, and info is lower than warning. Configure Python's logging with the level and handlers you want.

If logging isn't configured, Flask adds a handler for its own logger and sets the level to debug in debug mode, which is why the app.logger message shows up. Flask's docs show how to configure logging the way it does and other examples.

from logging.config import dictConfig

dictConfig({
    'version': 1,
    'formatters': {'default': {
        'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
    }},
    'handlers': {'wsgi': {
        'class': 'logging.StreamHandler',
        'stream': 'ext://flask.logging.wsgi_errors_stream',
        'formatter': 'default'
    }},
    'root': {
        'level': 'INFO',
        'handlers': ['wsgi']
    }
})

app = Flask(__name__)

from project import util
util.test()

If you import util before calling dictConfig, you'll notice that the logging still doesn't work. This is because Python will disable existing loggers when configuring. You can prevent that by adding 'disable_existing_loggers': False to the config, but this comes with the tradeoff that you might see duplicate logs if a logger was already configured. Alternatively, don't get logger at the module level, get it inside the function when it's needed.


If you specifically want to use the app's logger elsewhere, you need to import the app. Since this is prone to circular import errors, or even impossible when using an app factory, use current_app instead to access the app during requests.

from flask import current_app

def test():
    current_app.logger.info('info message from util')

Upvotes: 5

Calumah
Calumah

Reputation: 3005

Use current_app to access the app's logger:

from flask import current_app

def test():
    current_app.logger.info("info message from util")

This allow you to use the default Flask logger.

More information: http://flask.pocoo.org/docs/logging/

Upvotes: 12

Related Questions