Skip to content
This page has been auto-translated and may contain errors.View in English

Salida y entrada ​

Hay dos herramientas que vas a usar desde la primera línea que escribas: print() muestra valores en la terminal e input() obtiene texto del usuario. Son sencillas, pero saber cómo se comportan te ahorra algunas sorpresas al principio.

print() e input() son las funciones estándar de entrada/salida por terminal de Python. Ambas son más configurables de lo que parecen a primera vista. print() acepta argumentos que controlan cómo se unen los valores y cómo termina la salida. input() siempre devuelve una cadena de texto, algo que determina cómo debes manejar cada valor que viene del usuario.

Internamente, print() escribe en sys.stdout e input() lee desde sys.stdin (los flujos estándar de salida y entrada a los que está conectada tu terminal). Ambos trabajan solo con texto, y la salida está almacenada en búfer (buffered) por defecto: Python la retiene brevemente y la escribe en bloques en lugar de un carácter a la vez. Dos consecuencias importan en programas reales: la salida va a un flujo distinto del de los errores (stdout frente a stderr), y puedes forzar el vaciado de ese búfer cuando necesitas que la salida aparezca de inmediato.

Cómo ejecuta Python tu código ​

Python ejecuta tu código de arriba hacia abajo, una línea a la vez, exactamente en el orden en que lo escribiste. No salta de un lado a otro. El orden en que escribes las cosas es el orden en que se ejecutan. Siempre.

python
ciudad = "Ciudad de México"
print(ciudad)
print("Población: 9 millones")

Primero se asigna ciudad. Se ejecuta el primer print. Se ejecuta el segundo print. Siempre en ese orden.

Esto importa porque no puedes usar una variable antes de haberla asignado. Python todavía no la conoce y va a lanzar un error:

python
print(pais)   # NameError: pais aún no está definida
pais = "México"

Ten esto en cuenta a medida que crecen tus programas: todo lo que uses debe estar definido antes de usarlo.

Python usa ejecución secuencial: cada instrucción se evalúa en el momento en que se encuentra, en una sola pasada de arriba hacia abajo por el archivo. No hay un escaneo previo de todo el archivo. Referenciar un nombre antes de asignarlo lanza un NameError exactamente en esa línea, no antes.

python
ciudad = "Ciudad de México"
print(ciudad)             # funciona: ciudad ya está asignada
print(pais)                # NameError: aún no está asignada
pais = "México"

La regla: las dependencias deben estar definidas antes de la línea que las usa.

Python ejecuta tu archivo en una sola pasada de arriba hacia abajo, y solo busca un nombre en el momento en que esa línea se ejecuta de verdad, no cuando lee el archivo por primera vez. Por eso un nombre inexistente produce un NameError en tiempo de ejecución (cuando la línea se ejecuta) y no un error apenas guardas el archivo. No existe el hoisting (la forma en que JavaScript mueve silenciosamente las declaraciones var al inicio de su ámbito) ni las declaraciones adelantadas (la forma en que C te permite prometer un nombre ahora y definirlo después). Un nombre existe en el momento en que se le asigna algo, y usarlo antes de eso lanza un error.

python
print(pais)   # NameError en tiempo de ejecución, no un error de sintaxis
pais = "México"
JunoCómo ejecuta Python tu código Python lee tu archivo de arriba hacia abajo, una línea a la vez, en el orden en que lo escribiste. La trampa en la que todos caen alguna vez: un nombre debe existir antes de la línea que lo usa, o te vas a encontrar con un NameError. No hay adelantos ni una lectura previa de todo el archivo.
JunoCómo ejecuta Python tu código De arriba hacia abajo, en una sola pasada, en orden. Un nombre debe estar asignado antes de cualquier línea que lo use, o va a ser un NameError justo en esa línea. No hay escaneo previo del archivo.
JunoCómo ejecuta Python tu código Una sola pasada de arriba hacia abajo, con los nombres buscados a medida que se ejecuta cada línea. Usa un nombre antes de asignarlo y te va a saltar un NameError en tiempo de ejecución, no un error de sintaxis. Python no hace hoisting y no tiene declaraciones adelantadas, así que el orden lo es todo.

Imprimir salida ​

print() es la forma en que Python te responde. Le pasas cualquier valor y lo muestra. Convierte automáticamente lo que le des a texto.

print() convierte cada argumento a una cadena mediante str(), los une con un separador (un espacio por defecto) y luego escribe el resultado seguido de un salto de línea en la salida estándar. Entender los valores por defecto hace que los argumentos opcionales sean más predecibles.

La firma completa de print() es print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False). El colector *objects acepta cualquier cantidad de argumentos posicionales y llama a str() sobre cada uno. sep y end controlan el formato; file redirige la salida a cualquier flujo que se pueda escribir; flush fuerza el vaciado inmediato del búfer.

python
print("Hola")     # Hola
print(42)         # 42
print(3.14)       # 3.14
print(True)       # True

Múltiples valores ​

Puedes imprimir varios valores a la vez separándolos con comas. Python pone un espacio entre ellos por defecto. Cambia el separador con sep:

Cada uno de los argumentos posicionales se convierte individualmente con str(), y luego se unen con sep. El valor por defecto de sep es un solo espacio. Sobrescribirlo te permite producir salida formateada sin concatenar cadenas:

print() no construye una sola cadena y la escribe; escribe cada argumento en el flujo por turnos (llamando a str() sobre cada uno), con sep entre ellos y end al final. Como esas escrituras ocurren una a la vez en lugar de como una única operación bloqueada, dos llamadas a print() ejecutándose al mismo tiempo (en hilos distintos) pueden entrelazar su salida. Cuando eso importa, construye una sola cadena e imprímela una vez. Para el uso diario, sobrescribir sep sigue siendo mejor que pegar cadenas a mano:

python
nombre = "Ana"
edad = 28
print(nombre, edad)                     # Ana 28
print("Nombre:", nombre)                # Nombre: Ana
print("2024", "01", "15", sep="-")     # 2024-01-15
print("a", "b", "c", sep=", ")         # a, b, c

Controlar el final de línea ​

Cada llamada a print() termina con un salto de línea por defecto, así que la siguiente salida empieza en una línea nueva. Cambia eso con end. Poner end="" hace que el siguiente print continúe en la misma línea:

El parámetro end reemplaza el salto de línea por defecto. Pon "" para suprimir el salto de línea, " " para quedarte en la misma línea con un espacio, o cualquier otra cadena. Combinado con sep, puedes producir la mayoría de los formatos de salida sin construir cadenas manualmente:

sep y end son de solo palabra clave (los pasas por nombre, como end="", nunca por posición), y por defecto valen un espacio y un salto de línea. end="" es la forma habitual de imprimir una línea parcial y dejar que la siguiente llamada la continúe. Para salidas que necesitan aparecer en el momento en que ocurren, como un indicador de progreso o un registro en vivo, agrega flush=True para que Python escriba de inmediato en lugar de esperar un salto de línea o a que se llene el búfer.

python
print("Cargando", end="")
print("...")
# Cargando...

print("uno", end=" | ")
print("dos", end=" | ")
print("tres")
# uno | dos | tres
JunoImprimir salidaprint() convierte en texto lo que le pases y lo muestra. Pásale varias cosas separadas por comas y vas a obtener un espacio entre ellas; cámbialo con sep. Cada print baja a una línea nueva al final; end="" mantiene el siguiente en la misma línea.
JunoImprimir salidaprint() aplica str() a cada argumento, los une con sep (un espacio por defecto) y termina con end (un salto de línea por defecto). Sobrescribe cualquiera de los dos para formatear la salida sin pegar cadenas a mano.
JunoImprimir salidaprint() escribe cada argumento pasándolo por str(), con sep entre ellos y end al final, ambos de solo palabra clave. Usa end="" para continuar una línea, y flush=True cuando la salida necesite aparecer de inmediato.

Dar formato a la salida con f-strings ​

La forma más limpia de armar mensajes es con f-strings. Pon f antes de la comilla de apertura y luego envuelve cualquier variable o expresión entre llaves. Python la completa en tiempo de ejecución. Puedes poner cualquier valor, cálculo o llamada a método dentro de {}.

Las f-strings evalúan cualquier expresión dentro de {} en tiempo de ejecución e insertan el resultado como texto. Los dos puntos después del valor introducen una especificación de formato: una sintaxis compacta para controlar decimales, alineación y formato de números. Son más rápidas y legibles que la concatenación, y no requieren llamadas explícitas a str().

Cada {} en una f-string termina llamando a format(value, spec), que a su vez delega en el método propio del valor __format__ (un dunder, el método de doble guion bajo que Python invoca para formatear un valor). Así, cualquier clase puede decidir cómo se ve dentro de una f-string definiendo __format__. Las banderas de conversión !r, !s y !a ejecutan repr(), str() o ascii() sobre el valor antes de mostrarlo; !r es la que vale la pena recordar para depurar, porque muestra un valor tal como lo escribirías en código (comillas, escapes y todo), como se ve a continuación.

python
nombre = "Ana"
puntaje = 980

# concatenación: tosco, requiere str() para números
print("Jugador: " + nombre + ", Puntaje: " + str(puntaje))

# f-string: legible, sin conversión manual
print(f"Jugador: {nombre}, Puntaje: {puntaje}")

Puedes poner cualquier expresión dentro de {}: aritmética, llamadas a métodos (como .upper(), que se cubre a fondo en el capítulo de Cadenas de texto), especificaciones de formato:

python
precio = 49.99
impuesto = 0.2
total = precio * (1 + impuesto)

print(f"Total: {total:.2f}")          # Total: 59.99
print(f"Nombre: {nombre.upper()}")    # Nombre: ANA
print(f"2 + 2 = {2 + 2}")             # 2 + 2 = 4

La especificación de formato después de : controla cómo se muestra el valor:

python
ratio = 0.8765
cantidad = 1234567
etiqueta = "ingresos"

print(f"{ratio:.1%}")       # 87.6%
print(f"{cantidad:,}")      # 1,234,567
print(f"{etiqueta:>12}")    # "    ingresos"

:.2f significa "dos decimales". Lo vas a usar todo el tiempo para precios y medidas. Todo lo demás está ahí para cuando lo necesites. Lo importante: dentro de {} puede ir cualquier cosa, no solo nombres de variables.

:.2f y :.0% cubren la mayoría de las necesidades de formato. Los especificadores de alineación (>, <, ^) junto con un ancho producen salidas tabulares prolijas. El patrón general es {valor:[alineación][ancho][.precisión][tipo]}. Una vez que reconoces las partes, cualquier especificación se vuelve legible sin tener que memorizar todas las combinaciones.

La misma especificación puede significar cosas distintas para tipos distintos, porque cada tipo se formatea a su manera. f"{'hi':5}" rellena el texto por la derecha (el texto se alinea a la izquierda por defecto), mientras que f"{42:5}" rellena por la izquierda (los números se alinean a la derecha): el mismo :5, resultado opuesto. Cada tipo integrado tiene sus propias reglas para este minilenguaje de formato, y una clase personalizada define las suyas implementando __format__.

JunoDar formato a la salida con f-strings Pon f antes de la comilla de apertura y envuelve lo que sea entre {}: una variable, una suma, hasta una llamada a método. Los dos puntos agregan formato, como :.2f para dos decimales. Mucho más limpio que pegar cadenas con +.
JunoDar formato a la salida con f-stringsf"..." inserta el resultado de cualquier expresión directo en la cadena, sin necesitar str(). Después de los dos puntos viene la especificación de formato: :.2f, :,, :>12 y compañía. Más limpio y rápido que la concatenación.
JunoDar formato a la salida con f-strings Cada {} llama al propio __format__ del valor, así que la especificación después de los dos puntos significa lo que ese tipo decida. !r es la que hay que recordar: muestra un valor tal como lo escribirías, lo que hace que espacios en blanco perdidos y otras cosas invisibles salten a la vista cuando estás depurando.

Obtener información del usuario ​

input() pausa tu programa y espera a que el usuario escriba algo. Lo que sea que escriba (y confirme con Enter) vuelve como el valor de retorno. La cadena entre paréntesis es el mensaje que ve el usuario.

python
nombre = input("¿Cómo te llamas? ")
print(f"¡Hola, {nombre}!")

input() siempre devuelve una cadena de texto, sin importar qué escriba el usuario. Escribe 42 y vas a recibir "42", no el número 42. Para hacer operaciones aritméticas con ese valor, conviértelo explícitamente:

python
edad = int(input("¿Cuántos años tienes? "))
print(f"En diez años vas a tener {edad + 10}.")

¿Qué pasa si el usuario escribe algo que no se puede convertir? Python lanza un ValueError. Cómo manejar eso correctamente se cubre en el capítulo de Archivos y excepciones.

input() escribe el mensaje en la salida estándar, lee una línea de la entrada estándar, elimina el salto de línea final y devuelve el resultado como una cadena de texto. No hay inferencia de tipo. Todo lo que llega de la terminal llega como texto; declaras el tipo que necesitas convirtiendo explícitamente en el punto de entrada.

python
nombre = input("¿Cómo te llamas? ")
edad = int(input("¿Cuántos años tienes? "))

Este patrón (recibir texto, convertirlo al tipo que necesitas) se aplica en cualquier lugar donde llegan datos externos. int(), float() y str() son las herramientas de conversión. Si la cadena no se puede convertir, Python lanza un ValueError, que se cubre en el capítulo de Archivos y excepciones.

input() es un envoltorio sencillo: escribe el mensaje en sys.stdout (salida estándar), lo vacía para que el mensaje aparezca antes de que el programa se bloquee, lee una línea de sys.stdin (entrada estándar), elimina el salto de línea final y devuelve un str. Siempre es un str por diseño, porque Python no puede adivinar si "42" se pensó como un entero, un decimal o texto literal. Así que conviertes en el punto de entrada. Esta es la forma fundamental de la entrada/salida en Python: los datos externos llegan como texto, y tu código decide su tipo en el punto donde entran.

python
nombre = input("Ingresa tu nombre: ")
puntaje = float(input("Ingresa tu puntaje (0.0 a 1.0): "))

print(f"Nombre:  {nombre!r}")   # !r revela cualquier espacio en blanco invisible
print(f"Puntaje: {puntaje:.1%}")
JunoObtener información del usuarioinput() muestra tu mensaje, espera una línea y siempre la devuelve como string, aunque hayan escrito un número. ¿Necesitas un número? Convíértelo tú mismo con int() o float() al recibirlo, y luego sigue trabajando con el tipo correcto.
JunoObtener información del usuarioinput() siempre devuelve un str, sin inferencia de tipo. Convierte en el punto de entrada con int() o float(), y espera un ValueError si el texto no se puede interpretar. Ese patrón de recibir y luego convertir aparece en todos los lugares donde llegan datos externos.
JunoObtener información del usuario Todo lo que viene de input() es un str por diseño, porque Python no puede adivinar qué quisiste decir. Convierte en el punto de entrada y maneja el ValueError cuando no se pueda interpretar. Es la misma forma que en cualquier otro lugar donde llegan datos externos.

Escribir en stderr ​

Por defecto, print() escribe en la salida estándar: el flujo que aparece en la terminal y que fluye a través de las tuberías (pipes). Python también tiene la salida de error estándar (stderr), un flujo separado para diagnósticos y advertencias. Se ven idénticos en una terminal, pero son distintos: cuando canalizas la salida de un script hacia otro comando, solo pasa stdout. Stderr siempre llega a la terminal.

Escribir en stderr usa el argumento file de print(). Eso requiere importar sys, algo que se cubre en el capítulo de Módulos. Por ahora, basta con saber que existen los dos flujos y por qué están separados.

En la práctica ​

Un cuestionario que se personaliza a partir de lo que escribe el usuario:

python
nombre = input("¿Cómo te llamas? ")
materia = input("¿Qué materia? ")

print(f"Listo, {nombre}. Empezando tu cuestionario de {materia}.")
print("¡Buena suerte!")

Ambas entradas vuelven como cadenas de texto y van directo a las f-strings. No hace falta convertirlas porque las estás usando como texto, no como números.

Un conversor de temperatura con salida tabular alineada:

python
celsius = float(input("Temperatura en Celsius: "))
fahrenheit = celsius * 9 / 5 + 32

print(f"{'Celsius':>12} {'Fahrenheit':>12}")
print(f"{celsius:>12.1f} {fahrenheit:>12.1f}")

float() maneja tanto enteros como decimales que ingrese el usuario. La especificación >12 mantiene las columnas alineadas sin importar cuántos dígitos tengan los números. Prueba escribiendo 100 y -40: la salida se mantiene ordenada en ambos casos.

Usar !r para mostrar exactamente lo que recibió Python, útil cuando la salida se ve rara:

python
nombre = input("Ingresa tu nombre: ")
puntaje = float(input("Ingresa tu puntaje (0.0 a 1.0): "))

print(f"Nombre:   {nombre!r}")
print(f"Puntaje:  {puntaje!r}")
print()
print(f"Resultado: {nombre}: {puntaje:.1%}")

{nombre} y {nombre!r} se muestran igual cuando la entrada está limpia. La diferencia aparece cuando hay espacios finales u otros caracteres invisibles. Acostumbrarte a usar !r mientras depuras hace que los valores inesperados se vuelvan visibles de inmediato.