HOWTO · Python

Iniciar sesión en stdout en Python

Podemos usar las funciones logging.basicConfig() y logging.StreamHandler() para iniciar sesión en stdout en Python.

En esta página

Para enviar mensajes de registro de Python a la salida estándar (stdout), configura logging.basicConfig() con stream=sys.stdout. Si necesitas más control, añade logging.StreamHandler(sys.stdout) a un registrador. Usa un FileHandler independiente junto con el controlador de flujo cuando quieras enviar los mismos registros tanto a la consola como a un archivo.

Registrar mensajes en stdout con la función logging.basicConfig() de Python

Para configurar el registro en toda una aplicación de forma sencilla, logging.basicConfig() configura el registrador raíz. El parámetro stream selecciona el flujo de salida; de forma predeterminada, el registro usa sys.stderr. Asígnale sys.stdout para enviar los registros a la salida estándar. level controla qué registros acepta el registrador raíz y format determina el formato de cada línea emitida.

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() es una forma práctica de configurar el registrador raíz una sola vez. Si otra parte de la aplicación ya añadió un controlador al registrador raíz, una llamada posterior mantiene esa configuración; por tanto, cambiar stream aquí no redirigirá la salida. En Python 3.8 y versiones posteriores, force=True elimina los controladores existentes del registrador raíz antes de aplicar esta configuración. Úsalo solo si tu código debe reemplazar la configuración de registro de la aplicación; de lo contrario, configura el registro una vez en el punto de entrada de la aplicación.

Las opciones filename y filemode configuran la salida a un archivo: filename indica el nombre del archivo, mientras que filemode determina cómo se abre y, de forma predeterminada, añade contenido ("a"). No pases filename y stream juntos a basicConfig(); elige un solo destino aquí. Para enviar registros tanto a la salida estándar como a un archivo, usa controladores independientes, como se muestra más abajo. Además, basicConfig() solo configura el registrador raíz si este aún no tiene controladores, a menos que se use force=True (disponible desde Python 3.8).

Registrar mensajes en stdout con la función logging.StreamHandler() de Python

Usa un controlador explícito cuando necesites controlar un registrador con nombre o combinar destinos. De forma predeterminada, logging.StreamHandler() escribe en sys.stderr, así que pasa sys.stdout explícitamente. Tanto el nivel del registrador como el del controlador afectan a los registros emitidos: cada registro debe cumplir ambos. Este ejemplo crea un controlador para stdout y otro para un archivo, y luego añade ambos al mismo registrador.

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

Cada controlador da formato al registro y lo escribe en su propio destino. El archivo se crea en el directorio temporal del sistema, y mode="w" reemplaza el archivo del ejemplo en cada ejecución. En una aplicación de larga duración, configura los controladores una sola vez en lugar de añadirlos repetidamente; los controladores duplicados pueden hacer que cada registro aparezca más de una vez. En producción, gestiona la ruta del archivo y el ciclo de vida de los controladores según las necesidades de tu aplicación.

Conclusión

Usa logging.basicConfig() con stream=sys.stdout para configurar rápidamente el registrador raíz. Elige logging.StreamHandler(sys.stdout) cuando necesites controlar un registrador con nombre, personalizar la configuración de los controladores o usar varios destinos. Un StreamHandler sin un flujo explícito escribe en stderr, y para registrar tanto en un archivo como en la consola se necesitan controladores de flujo y de archivo independientes.