Módulo 2 · Lección 2 de 28
Controlar la salida en pantalla
Los parámetros de print que casi nadie usa, escribir sin salto de línea, reescribir la línea actual, limpiar la pantalla y medir su ancho.
Llevas dos módulos usando print para una sola cosa: escribir una línea y bajar a la siguiente. Con eso se puede hacer un programa que funcione, pero no uno que se vea bien. Un programa de terminal decente escribe en el sitio exacto, no baja de línea cuando no le toca y sabe cuánto espacio tiene.
Todo eso está en print y en un par de módulos de la biblioteca estándar. No hace falta instalar nada.
print acepta varios valores#
Cuando le pasas más de un valor separados por comas, print los imprime todos con un espacio entre medias y convierte cada uno a texto por su cuenta. No hace falta str() ni sumar cadenas:
edad = 34
print("Tienes", edad, "años")Tienes 34 añosEse espacio de separación no es obligatorio: es el valor por defecto de un parámetro llamado sep.
sep: qué se pone entre los valores#
print("uno", "dos", "tres")
print("uno", "dos", "tres", sep="")
print("uno", "dos", "tres", sep=" | ")
print("2026", "09", "19", sep="-")
print("ruta", "a", "un", "sitio", sep="/")uno dos tres
unodostres
uno | dos | tres
2026-09-19
ruta/a/un/sitioCombinado con el desempaquetado que viste en la lección de argumentos variables, sep sirve para imprimir una lista entera en una línea:
partes = ["rojo", "verde", "azul"]
print(*partes, sep=", ")rojo, verde, azulend: qué se pone al final#
El salto de línea del final tampoco es obligatorio. print termina con "\n" porque ese es el valor por defecto de end. Si lo cambias por una cadena vacía, el cursor se queda donde está y el siguiente print continúa en la misma línea:
print("Cargando", end="")
print(".", end="")
print(".", end="")
print(".", end="")
print(" listo")Cargando... listoCinco llamadas a print y una sola línea de salida. Esto es lo que permite construir una línea por trozos, según se van calculando, que es justo lo que hace falta cuando el programa procesa cosas dentro de un bucle:
for numero in range(1, 6):
print(numero, end=" ")
print()1 2 3 4 5 Fíjate en el print() vacío del final. Es imprescindible: sin él, el cursor se queda colgado al final de la línea y el prompt de la terminal aparecerá pegado a tus números. Cada vez que uses end="" en un bucle, acuérdate de cerrar la línea al salir.
Y end puede ser cualquier cosa, no solo la cadena vacía:
print("primera", end="\n\n")
print("segunda")primera
segundaflush: por qué a veces no se ve nada#
Escribir en la pantalla es lento, así que Python no manda los caracteres uno a uno: los acumula en una memoria intermedia, el búfer, y los suelta de golpe cuando hay un salto de línea o cuando el programa termina.
Mientras cada print acabe en \n, no lo notas. En cuanto usas end="", sí:
import time
for i in range(1, 4):
print(f"paso {i}", end=" ")
time.sleep(0.2)
print("fin")Sin flush, en muchas terminales verás la pantalla vacía durante seis décimas y luego todo de golpe. El programa está trabajando, pero parece colgado. La solución es pedir explícitamente que se vacíe el búfer:
import time
for i in range(1, 4):
print(f"paso {i}", end=" ", flush=True)
time.sleep(0.2)
print("fin")paso 1 paso 2 paso 3 finLa salida final es idéntica; lo que cambia es cuándo aparece cada trozo. Con flush=True los pasos se ven salir uno a uno.
El búfer también explica una rareza que verás en cuanto redirijas la salida de un programa a un fichero. Con este programa:
import sys
print("línea a stdout")
print("línea a stderr", file=sys.stderr)
print("otra a stdout")
print("otra a stderr", file=sys.stderr)python3 orden.py 2>&1 | catlínea a stderr
otra a stderr
línea a stdout
otra a stdoutEl orden está del revés. La razón es que, cuando la salida no va a una terminal, Python acumula lo de stdout en bloques grandes, mientras que stderr sale siempre de inmediato. En la terminal se ven en orden; en un fichero, no.
Reescribir la línea con \r#
El carácter \r, el retorno de carro, no baja de línea: devuelve el cursor al principio de la línea actual. Lo que imprimas después pisa lo que había.
import time
for restantes in range(3, 0, -1):
print(f"\rEmpieza en {restantes}...", end="", flush=True)
time.sleep(1)
print("\rYa ")En la terminal no se ven tres líneas, se ve una sola línea que cambia: primero Empieza en 3..., luego el 3 se convierte en 2, luego en 1. Lo que Python manda a la salida es exactamente esto:
\rEmpieza en 3...\rEmpieza en 2...\rEmpieza en 1...\rYa \nEs la base de los contadores, los spinners y las barras de progreso de la última lección del bloque.
Limpiar la pantalla#
Un menú que se redibuja necesita empezar con la pantalla limpia. No hay una función de Python para esto, porque el comando depende del sistema, así que se envuelve en una función propia:
import os
def limpiar_pantalla() -> None:
"""Borra la pantalla en Windows, macOS y Linux."""
os.system("cls" if os.name == "nt" else "clear")os.name vale "nt" en Windows y "posix" en macOS y Linux:
import os
print(os.name)posixos.system arranca otro programa, y eso es lento y no funciona si la salida está redirigida. La alternativa es mandar el código de escape que significa "borra la pantalla y pon el cursor arriba a la izquierda":
def limpiar_pantalla() -> None:
print("\033[2J\033[H", end="")Funciona en cualquier terminal moderna, incluida la de Windows 10 en adelante, y no arranca ningún proceso. Los detalles de esos códigos son el tema de la lección de colores.
Escribir directamente en stdout y stderr#
print es una comodidad construida encima de algo más básico: sys.stdout, el fichero de la salida estándar. Escribir ahí directamente tiene dos diferencias importantes:
import sys
print("stdout normal")
sys.stdout.write("escrito con write\n")
sys.stdout.write("sin salto")
sys.stdout.write(" y sigue\n")
cuantos = sys.stdout.write("cuenta\n")
print(cuantos)stdout normal
escrito con write
sin salto y sigue
cuenta
7La primera diferencia es que write no añade nada: ni separadores ni salto de línea, tienes que ponerlos tú. La segunda es que devuelve el número de caracteres escritos, siete en ese último caso contando el \n.
Todo programa tiene además una segunda salida, sys.stderr, pensada para los mensajes que no son el resultado del trabajo: avisos, errores y diagnósticos. Se escribe igual, o con el parámetro file de print:
import sys
sys.stderr.write("esto va a error\n")
print("y esto también", file=sys.stderr)esto va a error
y esto tambiénEn la terminal se ven juntas, así que la distinción parece inútil. No lo es: quien use tu programa con > para guardar el resultado en un fichero se llevará solo stdout, y los avisos seguirán apareciendo en su pantalla, que es exactamente lo que quiere. Los códigos de salida y la redirección tienen su lección en este módulo.
El ancho de la terminal#
Si dibujas una línea de 80 guiones en una ventana de 60 columnas, la terminal la parte en dos y el diseño se descuadra. La medida real está en shutil:
import shutil
tamano = shutil.get_terminal_size()
print(tamano)
print(tamano.columns, tamano.lines)os.terminal_size(columns=80, lines=24)
80 24Esos 80 por 24 son el valor de reserva, y salen porque este ejemplo se ha ejecutado con la salida redirigida a un fichero, donde no hay ninguna ventana que medir. En tu terminal verás las medidas de verdad. El valor de reserva se puede cambiar:
import shutil
print(shutil.get_terminal_size(fallback=(100, 30)).columns)100Con esa medida ya se puede adaptar la salida. Tres funciones que vas a reutilizar todo el módulo:
import shutil
def columnas() -> int:
"""Ancho útil de la terminal ahora mismo."""
return shutil.get_terminal_size().columns
def regla(caracter: str = "-") -> str:
"""Una línea horizontal de lado a lado."""
return caracter * columnas()
def titulo_centrado(texto: str, relleno: str = "=") -> str:
"""El texto centrado y rodeado del carácter de relleno."""
return f" {texto} ".center(columnas(), relleno)
def ajustar(texto: str) -> str:
"""Recorta el texto si no cabe en una línea."""
ancho = columnas()
if len(texto) <= ancho:
return texto
return texto[: ancho - 1] + "…"Probándolas en una salida de 80 columnas:
print(titulo_centrado("INFORME DE VENTAS"))
print(titulo_centrado("resumen", "-"))
print(regla())
largo = "Este mensaje es muy largo y no cabe en una terminal estrecha, así que hay que recortarlo antes de imprimirlo."
print(len(largo))
print(ajustar(largo))============================== INFORME DE VENTAS ===============================
----------------------------------- resumen ------------------------------------
--------------------------------------------------------------------------------
109
Este mensaje es muy largo y no cabe en una terminal estrecha, así que hay que r…El center es el mismo método de cadenas del módulo 1; lo único nuevo es que el ancho se calcula en vez de escribirse a mano.