HOWTO · Python

How to Log to Stdout in Python

Learn how to log messages to the standard output (stdout) in Python using the built-in logging module. Explore techniques for configuring logging levels, formatting log messages, and directing output to the console for effective debugging and monitoring in your Python applications.

On this page

To send Python log messages to standard output (stdout), configure logging.basicConfig() with stream=sys.stdout. For more control, attach a logging.StreamHandler(sys.stdout) to a logger. Use a separate FileHandler alongside the stream handler when the same records should go to both the console and a file.

Log to stdout With the logging.basicConfig() Function in Python

For a simple application-wide setup, logging.basicConfig() configures the root logger. Its stream parameter selects the output stream; by default, logging uses sys.stderr. Set it to sys.stdout to route records to standard output. The level controls which records pass the root logger, and format controls each emitted line.

import logging
import sys

logging.basicConfig(
    level=logging.INFO,
    format="%(levelname)s: %(message)s",
    stream=sys.stdout,
)

logging.info("Application started")
INFO: Application started

basicConfig() is a one-time convenience for the root logger. If another part of the application has already added a root handler, a later call leaves that setup in place, so changing stream here will not redirect its output. On Python 3.8 and later, force=True removes the existing root handlers before applying this configuration. Use it only when your code is responsible for replacing the application’s logging setup; otherwise, configure logging once at the application entry point.

The filename and filemode options configure file output: filename names the file, while filemode controls how it is opened and defaults to append mode ("a"). Do not pass filename and stream together to basicConfig(); choose one destination here. To send records to both standard output and a file, use separate handlers as shown below. Also, basicConfig() only configures the root logger when it has no handlers already, unless force=True is used (available in Python 3.8 and later).

Log to stdout With the logging.StreamHandler() Function in Python

Use an explicit handler when you need to control a named logger or combine destinations. logging.StreamHandler() writes to sys.stderr by default, so pass sys.stdout explicitly. The logger level and handler level both affect which records are emitted; a record must pass both. This example creates one stdout handler and one file handler, then attaches both to the same logger.

import logging
import sys
import tempfile
from pathlib import Path

log_path = Path(tempfile.gettempdir()) / "python-logging-example.log"
logger = logging.getLogger("example")
logger.setLevel(logging.INFO)
logger.propagate = False

formatter = logging.Formatter("%(levelname)s: %(message)s")
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.INFO)
stdout_handler.setFormatter(formatter)
file_handler = logging.FileHandler(log_path, mode="w", encoding="utf-8")
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)

logger.addHandler(stdout_handler)
logger.addHandler(file_handler)
logger.info("Application started")

for handler in (stdout_handler, file_handler):
    handler.close()
    logger.removeHandler(handler)
INFO: Application started

Each handler formats and writes the record to its own destination. The file is created in the system temporary directory, and mode="w" replaces the example file on each run. In a long-running application, configure handlers once rather than adding them repeatedly; duplicate handlers can cause each record to appear more than once. In production, manage the file path and handler lifecycle for your application.

Conclusion

Use logging.basicConfig() with stream=sys.stdout for a quick root-logger setup. Choose logging.StreamHandler(sys.stdout) when you need named-logger control, custom handler settings, or multiple destinations. A StreamHandler without an explicit stream writes to stderr, and file-plus-console logging requires separate stream and file handlers.