Entrada y salida en Python: print(), input() y formateo de strings

📅 Actualizado en marzo 2026 📊 Nivel: Principiante ⏱️ 17 min de lectura

Hay un momento muy concreto en que un programa deja de ser un ejercicio abstracto y se convierte en algo útil: cuando empieza a hablar con el usuario. Cuando le pregunta algo, espera la respuesta, y le devuelve algo significativo. Ese puente entre el programa y la persona que lo usa es la entrada y salida, y en Python tiene una elegancia que a mí todavía me sigue gustando después de años.

En esta lección vamos a explorar print() de verdad, no solo el uso básico que ya conoces, sino todos sus parámetros y los patrones que hacen el output realmente útil. Luego input(), con su trampa clásica de los tipos. Y después la parte que más me gusta enseñar: las f-strings, que son una de las razones por las que el código Python moderno es tan agradable de leer.

Ya has usado print() desde la primera lección. Pero probablemente lo has usado solo en su forma más simple: print("algo"). La función tiene cuatro parámetros opcionales que cambian completamente lo que puedes hacer con ella.

# La firma completa de print():
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

# Lo que ya conoces:
print("Hola, mundo")           # → Hola, mundo
print(42)                      # → 42
print(3.14)                    # → 3.14
print(True)                    # → True

# Varios valores a la vez:
print("Tu edad es", 28, "años")   # → Tu edad es 28 años
print(1, 2, 3, 4, 5)             # → 1 2 3 4 5

# Sin argumentos — imprime una línea vacía:
print()   # → (línea en blanco)

Esa última forma, print() sin argumentos, la uso constantemente para añadir espacio visual entre bloques de salida. Es más limpio que print("").

MacBook en plano cenital con ventana de código Python con syntax highlighting en pantalla oscura
MacBook con una ventana de código Python abierta, con syntax highlighting sobre fondo oscuro. Fuente: Pexels (licencia libre).

🔧 Los parámetros sep y end: más útiles de lo que parecen

sep controla qué carácter se pone entre los valores cuando imprimes varios a la vez. Por defecto es un espacio. end controla qué se pone al final de la línea. Por defecto es '\n' (salto de línea).

# sep: separador entre valores
print(2026, 3, 6, sep="-")          # → 2026-3-6
print("ruta", "al", "archivo", sep="/")  # → ruta/al/archivo
print("a", "b", "c", sep=", ")     # → a, b, c
print("junto", "todo", sep="")     # → juntotodo

# end: qué va al final
print("cargando", end="")
print("...")                        # → cargando...  (en la misma línea)

print("uno", end=" | ")
print("dos", end=" | ")
print("tres")                       # → uno | dos | tres

# Imprimir lista sin bucle explícito:
numeros = [1, 2, 3, 4, 5]
print(*numeros, sep=" → ")          # → 1 → 2 → 3 → 4 → 5
💡 Truco favorito: print(*lista, sep="\n") imprime cada elemento de la lista en su propia línea sin necesidad de un bucle. Es el atajo elegante que uso constantemente para debuggear listas rápidamente.

Barra de progreso en terminal con end y flush

import time

for i in range(1, 6):
    print(f"Procesando paso {i}/5...", end="\r", flush=True)
    time.sleep(0.5)

print("Completado.          ")   # espacios para borrar el texto anterior

El end="\r" vuelve al principio de la línea sin bajar, sobreescribiendo el mensaje anterior. El flush=True fuerza que aparezca inmediatamente. Sin él, en algunos sistemas el texto queda en el buffer y no se ve hasta que el programa termina.

El parámetro file acepta cualquier objeto con un método .write(). El uso más habitual: escribir a un archivo de log directamente con print(), sin importar el módulo logging.

import sys

# Imprimir en stderr (mensajes de error) en lugar de stdout
print("Error: archivo no encontrado", file=sys.stderr)

# Escribir a un archivo de log
with open("registro.log", "a") as log:
    print("2026-03-06 09:00 - Inicio de proceso", file=log)
    print("2026-03-06 09:01 - Paso 1 completado", file=log)
# El archivo queda cerrado automáticamente al salir del with

# Combinar con sep para generar CSV:
cabeceras = ["nombre", "edad", "ciudad"]
datos = ["Ana", 28, "Madrid"]
with open("datos.csv", "w") as f:
    print(*cabeceras, sep=",", file=f)
    print(*datos, sep=",", file=f)
ℹ️ Para logs de verdad: En proyectos reales usa el módulo logging, que da control sobre niveles de severidad, formato y destinos múltiples. La redirección con file= es útil para scripts simples o depuración rápida, no para sistemas en producción.

⌨️ input(): leer datos del usuario

input() detiene la ejecución del programa, muestra un mensaje opcional, y espera a que el usuario escriba algo y pulse Enter. Lo que devuelve es siempre un str.

# Forma básica
nombre = input("¿Cómo te llamas? ")
print(f"Hola, {nombre}!")

# Sin mensaje (no recomendable — el usuario no sabe qué hacer)
dato = input()

# El mensaje puede ser lo que quieras
print("Por favor, introduce tu nombre:")
nombre = input("> ")

# Captura múltiple
nombre = input("Nombre: ")
ciudad = input("Ciudad: ")
print(f"Registrado: {nombre} de {ciudad}")
⚠️ Pon siempre el espacio al final del mensaje: input("Tu nombre: ") en lugar de input("Tu nombre:"). Sin el espacio, el cursor queda pegado a los dos puntos y la línea queda visualmente incómoda para el usuario.

🔄 El problema con los tipos en input()

Esta es la trampa número uno para los principiantes, sin excepción. input() siempre devuelve un string, aunque el usuario escriba un número. Si necesitas operar con él matemáticamente, tienes que convertirlo explícitamente.

# El error clásico:
edad = input("Tu edad: ")   # el usuario escribe 28
print(edad + 10)            # TypeError: can only concatenate str (not "int") to str

# La solución: convertir al tipo correcto
edad = int(input("Tu edad: "))
print(edad + 10)            # → 38

# Para decimales:
precio = float(input("Precio: "))

# Pero ¿y si el usuario escribe algo que no es un número?
# La conversión falla con ValueError. La solución robusta:
try:
    edad = int(input("Tu edad: "))
except ValueError:
    print("Eso no es un número válido.")
    edad = 0

El patrón int(input(...)) con el try/except es tan común que conviene aprenderlo como una unidad. Cuando lleguemos al módulo de manejo de excepciones veremos formas más elegantes, pero por ahora esto es lo que necesitas.

# Patrón completo para pedir un número al usuario de forma robusta:
def pedir_entero(mensaje):
    while True:
        try:
            return int(input(mensaje))
        except ValueError:
            print("Por favor, introduce un número entero.")

edad = pedir_entero("Tu edad: ")
print(f"Tienes {edad} años.")

✨ f-strings: el formateo moderno

Las f-strings llegaron en Python 3.6 y cambiaron la forma en que todo el mundo escribe código Python. La idea es simple: pones una f antes de la comilla de apertura y puedes incluir expresiones Python directamente dentro del string usando llaves {}.

nombre = "Ana"
edad = 28
ciudad = "Madrid"

# La forma pre-f-strings (todavía válida pero más verbosa):
saludo = "Hola, %s. Tienes %d años y vives en %s." % (nombre, edad, ciudad)
saludo = "Hola, {}. Tienes {} años y vives en {}.".format(nombre, edad, ciudad)

# Con f-strings — mucho más limpio:
saludo = f"Hola, {nombre}. Tienes {edad} años y vives en {ciudad}."

# Las llaves pueden contener cualquier expresión Python:
f"El doble de tu edad es {edad * 2}"         # → "El doble de tu edad es 56"
f"Nombre en mayúsculas: {nombre.upper()}"    # → "Nombre en mayúsculas: ANA"
f"¿Eres mayor de edad? {'Sí' if edad >= 18 else 'No'}"  # → "¿Eres mayor de edad? Sí"
f"Suma: {2 + 2}"                             # → "Suma: 4"
Gafas de montura negra en primer plano sobre una superficie, con código colorido desenfocado en la pantalla del fondo
Gafas sobre una mesa con una pantalla de código colorido al fondo. Fuente: Pexels (licencia libre).

🎛️ f-strings avanzadas: formato, alineación y debug

Las f-strings tienen un mini-lenguaje de especificación de formato que te permite controlar decimales, ancho de campo, alineación y mucho más. La sintaxis es {valor:especificador}.

precio = 1234.5678
pi = 3.14159265358979

# Decimales
f"{precio:.2f}"         # → "1234.57"   (2 decimales, redondea)
f"{pi:.4f}"             # → "3.1416"

# Separador de miles
f"{1000000:,}"          # → "1,000,000"
f"{precio:,.2f}"        # → "1,234.57"

# Ancho de campo y alineación
f"{'izquierda':<20}"    # → "izquierda           " (alineado a la izq.)
f"{'centro':^20}"       # → "      centro        " (centrado)
f"{'derecha':>20}"      # → "           derecha" (alineado a la dcha.)
f"{42:>10}"             # → "        42"

# Relleno con un carácter específico
f"{'título':*^30}"      # → "************título************"
f"{42:0>5}"             # → "00042"

# Porcentaje
tasa = 0.1575
f"{tasa:.1%}"           # → "15.8%"

# Notación científica
f"{0.000123:.2e}"       # → "1.23e-04"

El truco de debug con = (Python 3.8+)

Uno de mis favoritos para depuración rápida:

x = 42
y = [1, 2, 3]
nombre = "Ana"

# En lugar de print("x =", x, "y =", y):
print(f"{x=}")          # → x=42
print(f"{y=}")          # → y=[1, 2, 3]
print(f"{nombre=}")     # → nombre='Ana'
print(f"{x=}, {y=}")    # → x=42, y=[1, 2, 3]

# También funciona con expresiones:
print(f"{x * 2 = }")    # → x * 2 = 84
💡 Reemplaza tus print de depuración: La próxima vez que necesites saber el valor de varias variables, usa print(f"{a=}, {b=}, {c=}") en lugar de print("a:", a, "b:", b, "c:", c). Menos teclas, más información.
Infografía: anatomía completa de la función print() en Python con sus cuatro parámetros y ejemplos de código
Los cuatro parámetros de print(): *objects (qué imprimir), sep (separador), end (carácter final) y file/flush (destino y volcado). Infografía: Ciberaula.

📋 Los otros métodos de formateo

Las f-strings son la opción por defecto en Python 3.6+, pero vale la pena conocer las alternativas porque las verás en código existente y hay casos donde son la herramienta correcta.

str.format()

# Posicional:
"Hola, {}. Tienes {} años.".format("Ana", 28)

# Con nombres (más legible en plantillas largas):
"{nombre} vive en {ciudad}.".format(nombre="Ana", ciudad="Madrid")

# Reutilización:
"{0} + {0} = {1}".format(5, 10)    # → "5 + 5 = 10"

# Mismo especificador de formato que f-strings:
"{:.2f}".format(3.14159)           # → "3.14"

.format() sigue siendo útil cuando necesitas plantillas de texto que defines en un lugar y rellenas en otro, o cuando el string viene de una base de datos o archivo de configuración.

Formateo antiguo con %

"Hola, %s" % "Ana"               # → "Hola, Ana"
"Precio: %.2f€" % 9.99           # → "Precio: 9.99€"
"%d items en %s" % (3, "cesta")  # → "3 items en cesta"

El operador % viene del estilo C y sigue funcionando, pero en código nuevo no tiene ventajas sobre las f-strings. Lo verás mucho en código de hace más de 5-8 años.

Infografía comparativa de los 4 métodos de formateo de strings en Python: %, .format(), f-strings y Template
Comparativa de los cuatro métodos de formateo: % (heredado), .format() (Python 2.6+), f-strings (recomendado, Python 3.6+) y Template. Con sintaxis, ejemplos y cuándo usar cada uno. Infografía: Ciberaula.

🛠️ Programa completo: tarjeta de presentación

Vamos a juntar todo lo visto en un programa que pide datos al usuario y genera una tarjeta de presentación formateada.

print("=== GENERADOR DE TARJETA DE PRESENTACIÓN ===")
print()

nombre   = input("Tu nombre completo: ")
cargo    = input("Tu cargo o profesión: ")
empresa  = input("Empresa u organización: ")
ciudad   = input("Ciudad: ")

try:
    anos_exp = int(input("Años de experiencia: "))
except ValueError:
    anos_exp = 0

ancho = 40
linea = "=" * ancho

print()
print(linea)
print(f"  {nombre.title():^{ancho - 4}}")
print(f"  {cargo:<{ancho - 4}}")
print(f"  {empresa:<{ancho - 4}}")
print(f"  📍 {ciudad:<{ancho - 6}}")
if anos_exp > 0:
    print(f"  ⭐ {anos_exp} años de experiencia")
print(linea)
print()

print(f"Tarjeta generada para {nombre.split()[0]}. ¡Listo!")

Ejemplo de ejecución con los datos de una persona:

# Entrada:
# Tu nombre completo: ana garcía
# Tu cargo o profesión: Desarrolladora Python
# Empresa u organización: Ciberaula
# Ciudad: Madrid
# Años de experiencia: 5

# Salida:
# ========================================
#          Ana García
#   Desarrolladora Python
#   Ciberaula
#   📍 Madrid
#   ⭐ 5 años de experiencia
# ========================================

🐛 Errores clásicos con entrada y salida

1. Olvidar convertir el resultado de input()

n = input("Un número: ")
print(n * 3)   # Si escribes 5: imprime "555" no 15
# Porque "5" * 3 = "555" en Python (repetición de string)

# Correcto:
n = int(input("Un número: "))
print(n * 3)   # → 15

2. Concatenar string + int sin convertir

edad = 28
print("Tengo " + edad + " años")    # TypeError

# Opciones correctas:
print("Tengo " + str(edad) + " años")
print("Tengo", edad, "años")
print(f"Tengo {edad} años")         # La más limpia

3. Olvidar las llaves en una f-string

nombre = "Ana"
print(f"Hola nombre")       # → "Hola nombre"  (sin las llaves no se sustituye)
print(f"Hola {nombre}")     # → "Hola Ana"  ✅

4. Usar f-string sin la f

nombre = "Ana"
saludo = "Hola, {nombre}"       # string normal, no f-string
print(saludo)                   # → "Hola, {nombre}"  (literal)

saludo = f"Hola, {nombre}"      # ✅

5. Llaves literales en una f-string

# Si necesitas imprimir llaves reales en una f-string, duplícalas:
f"El formato es {{variable}}"    # → "El formato es {variable}"
f"{{{nombre}}}"                   # → "{Ana}"

✅ Resumen y próximos pasos

print() tiene cuatro parámetros: sep para el separador entre valores, end para el final de línea, file para redirigir la salida y flush para escritura inmediata. input() siempre devuelve un string — recuerda convertir con int() o float() cuando sea necesario. Y para formatear strings, las f-strings son la opción por defecto en cualquier código Python moderno.

En la siguiente lección entramos en el control de flujo: if, elif y else. Con input() e if juntos ya puedes escribir programas interactivos reales que toman decisiones según lo que diga el usuario.

❓ Preguntas frecuentes

❓ Preguntas frecuentes sobre Entrada y salida en Python: print(), input() y formateo de strings

Las dudas más comunes respondidas de forma clara y directa.

Porque input() lee lo que el usuario escribe desde el teclado como texto plano, sin interpretar qué tipo de dato es. Si el usuario escribe "42", Python recibe la cadena "42", no el entero 42. Es responsabilidad del programador convertirlo con int(), float() u otro tipo si es necesario. Esto es un diseño deliberado: Python no asume qué tipo esperas.
Con print(a, b) Python separa los valores con un espacio (el valor por defecto de sep) y convierte cada uno automáticamente. Con print(str(a) + str(b)) primero concatenas manualmente los strings y luego imprimes el resultado, sin espacio. La primera forma es más limpia y más flexible. La concatenación manual tiene sentido si necesitas control total sobre el resultado antes de imprimirlo.
Sí, puedes incluir cualquier expresión Python válida dentro de {}: operaciones aritméticas (f"{2**10}"), llamadas a métodos (f"{nombre.upper()}"), operadores ternarios (f"{"par" if n%2==0 else "impar"}"), y más. Sin embargo, por legibilidad, si la expresión es muy larga es mejor calcularla antes y asignarla a una variable. Las f-strings son para simplificar, no para escribir lógica compleja.
Es una especificación de formato. El : introduce la parte de formato, .2 indica dos decimales, y f indica que es un número de punto flotante. Así f"{precio:.2f}" muestra siempre exactamente dos decimales. Hay muchas más opciones: :d para enteros, :e para notación científica, :% para porcentajes, :>10 para alineación derecha en un campo de 10 caracteres, entre otras.
No es malo técnicamente, pero sí más propenso a errores y menos legible. El problema más común: si intentas concatenar un string con un int sin convertirlo explícitamente obtienes un TypeError. Con f-strings o print(a, b) Python hace la conversión automáticamente. Para cadenas simples y pocas variables, el + puede funcionar bien, pero para cualquier cosa con formato usa f-strings.
Con el parámetro end: print("cargando...", end="") omite el salto de línea. Esto es especialmente útil para crear barras de progreso en la terminal o imprimir varios valores en la misma línea dentro de un bucle. Recuerda que si superpones texto en la misma línea necesitarás también flush=True para que aparezca inmediatamente, sobre todo en bucles con sleep().
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Entrada y salida en Python: print(), input() y formateo de strings? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

Todavía no hay mensajes. ¡Sé el primero en participar!