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

Salida y entrada

Dos herramientas que usarás desde la primera línea que escribas: print() muestra valores en la terminal, input() obtiene texto del usuario. Son simples, pero conocer cómo se comportan te evita sorpresas al principio.

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

Bajo el capó, print() escribe en sys.stdout e input() lee de sys.stdin (los flujos estándar de salida y entrada a los que tu terminal está conectada). Ambas trabajan solo con texto, y la salida está en buffer por defecto: Python la retiene brevemente y escribe en fragmentos en lugar de un carácter a la vez. Dos consecuencias importan en programas reales: la salida va a un flujo diferente del de los errores (stdout versus stderr), y puedes forzar que ese buffer se vacíe cuando necesites que la salida aparezca inmediatamente.

Cómo Python ejecuta tu código

Python ejecuta tu código de arriba a abajo, una línea a la vez, exactamente en el orden en que la escribiste. Sin saltos. El orden en que escribes las cosas es el orden en que se ejecutan. Siempre.

python
city = "México"
print(city)
print("Población: 21 millones")

city se asigna primero. Se ejecuta el primer print. Se ejecuta el segundo print. Cada vez, en ese orden.

Esto importa porque no puedes usar una variable antes de asignarla. Python aún no la ha visto y lanzará un error:

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

Mantén esto en mente conforme tus programas crecen: cualquier cosa que uses debe estar definida antes de usarla.

Python usa ejecución secuencial: cada instrucción se evalúa conforme se encuentra, en un único paso de arriba a abajo por el archivo. No hay un pre-análisis del archivo completo primero. Hacer referencia a un nombre antes de asignarlo lanza NameError exactamente en esa línea, no antes.

python
city = "México"
print(city)             # funciona: city ya está asignado
print(country)          # NameError: aún no asignado
country = "México"

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

Python ejecuta tu archivo en un único paso de arriba a abajo, y solo busca un nombre en el momento en que esa línea realmente se ejecuta, no cuando primero lee el archivo. Por eso un nombre faltante es un NameError en tiempo de ejecución (cuando la línea se ejecuta) en lugar de un error el instante en que guardas. No hay hoisting (la forma en que JavaScript mueve silenciosamente las declaraciones de var al inicio de su alcance) y sin declaraciones forward (la forma en que C te permite prometer un nombre ahora y definirlo después). Un nombre existe en el momento en que se asigna, y cualquier uso antes de eso lanza un error.

python
print(country)   # NameError en tiempo de ejecución, no error de sintaxis
country = "México"
JunoCómo Python ejecuta tu código Python lee tu archivo de arriba a abajo, una línea a la vez, en el orden en que la escribiste. El problema que atrapa a todos una vez: un nombre tiene que existir antes de la línea que lo usa, o obtienes un NameError. Sin saltos, sin leer primero el archivo completo.
JunoCómo Python ejecuta tu código De arriba a abajo, un paso, en orden. Un nombre tiene que estar asignado antes de cualquier línea que lo use, de lo contrario es un NameError en esa línea exacta. Sin pre-análisis del archivo.
JunoCómo Python ejecuta tu código Un paso de arriba a abajo, nombres buscados conforme cada línea se ejecuta. Usa un nombre antes de que esté asignado y obtienes un NameError en tiempo de ejecución, no un error de sintaxis. Python no hace hoisting y no tiene declaraciones forward, así que el orden realmente lo es todo.

Imprimiendo salida

print() es cómo Python te habla de nuevo. Pásale cualquier valor e imprime ese valor. Convierte automáticamente lo que le des a texto.

print() convierte cada argumento a una cadena vía str(), los une con un separador (un espacio por defecto), luego escribe el resultado seguido de una nueva línea a la salida estándar. Entender los valores por defecto hace los argumentos opcionales 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() en cada uno. sep y end controlan el formato; file redirige la salida a cualquier flujo escribible; flush fuerza al buffer a vaciarse inmediatamente.

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

Múltiples valores

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

Múltiples argumentos posicionales se convierten con str() individualmente, luego se unen por sep. El sep por defecto es un único espacio. Sobrescribirlo te permite producir salida formateada sin concatenación de cadenas:

print() no construye una cadena y la escribe; escribe cada argumento en el flujo a su vez (llamando a str() en cada uno), con sep entre y end al final. Como esas escrituras suceden una a la vez en lugar de como una operación bloqueada única, dos llamadas a print() ejecutándose simultáneamente (en diferentes hilos) pueden intercalar su salida. Cuando eso importa, construye una cadena y imprímela una vez. Para uso cotidiano, sobrescribir sep sigue siendo mejor que pegar cadenas juntas a mano:

python
name = "María"
age = 28
print(name, age)                        # María 28
print("Name:", name)                    # Name: María
print("2024", "01", "15", sep="-")     # 2024-01-15
print("a", "b", "c", sep=", ")         # a, b, c

Controlando el final de línea

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

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

sep y end son solo por palabra clave (los pasas por nombre, como end="", nunca por posición), con valores por defecto de un espacio y una nueva línea. end="" es la forma estándar de imprimir una línea parcial y dejar que la siguiente llamada la continúe. Para salida que necesita aparecer conforme sucede, como un indicador de progreso o un registro en vivo, agrega flush=True para que Python escriba inmediatamente en lugar de esperar una nueva línea o a que su buffer se llene.

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

print("one", end=" | ")
print("two", end=" | ")
print("three")
# one | two | three
JunoImprimiendo salidaprint() convierte lo que le des en texto y lo muestra. Pasa varias cosas separadas por comas y obtienes un espacio entre ellas, cambia eso con sep. Cada print baja a una línea nueva al final; end="" mantiene el siguiente en la misma línea.
JunoImprimiendo salidaprint() ejecuta str() en cada argumento, los une con sep (un espacio por defecto), y termina con end (una nueva línea por defecto). Sobrescribe cualquiera de los dos para formatear salida sin pegar cadenas juntas.
JunoImprimiendo salidaprint() escribe cada argumento a través de str(), con sep entre y end al final, ambos solo por palabra clave. Recurre a end="" para continuar una línea, y flush=True cuando la salida necesita mostrarse de inmediato.

Formateando salida con f-strings

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

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

Cada {} en un f-string termina llamando a format(value, spec), que lo entrega al método __format__ del valor (un dunder, el método de doble guion bajo que Python llama para formatear un valor). Así que cualquier clase puede decidir cómo se ve dentro de un f-string definiendo __format__. Las banderas de conversión !r, !s, y !a ejecutan repr(), str(), o ascii() en el valor primero; !r es la que recordar para depuración, porque muestra un valor de la forma en que lo escribirías en código (comillas, escapes y todo), mostrado en la práctica a continuación.

python
name = "María"
score = 980

# concatenation: clunky, requires str() for numbers
print("Player: " + name + ", Score: " + str(score))

# f-string: readable, no manual conversion
print(f"Player: {name}, Score: {score}")

Puedes poner cualquier expresión dentro de {}: aritmética, llamadas a métodos (como .upper(), cubierto completamente en el capítulo Strings), especificaciones de formato:

python
price = 49.99
tax = 0.2
total = price * (1 + tax)

print(f"Total: {total:.2f}")          # Total: 59.99
print(f"Name: {name.upper()}")        # Name: MARÍA
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
count = 1234567
label = "revenue"

print(f"{ratio:.1%}")       # 87.6%
print(f"{count:,}")         # 1,234,567
print(f"{label:>12}")       # "     revenue"

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

:.2f y :.0% cubren la mayoría de necesidades de formato. Los especificadores de alineación (>, <, ^) con un ancho producen una salida tabular limpia. El patrón general es {value:[align][width][.precision][type]}. Una vez que reconoces las partes, cualquier especificación es legible sin memorizar todas las combinaciones.

La misma especificación puede significar cosas diferentes para tipos diferentes, porque cada tipo se formatea a sí mismo. f"{'hi':5}" rellena texto a la derecha (el texto se alinea a la izquierda por defecto) mientras f"{42:5}" rellena a la izquierda (los números se alinean a la derecha): el mismo :5, resultado opuesto. Cada tipo integrado lleva sus propias reglas para este mini-lenguaje de formato, y una clase personalizada establece las suyas definiendo __format__.

JunoFormateando salida con f-strings Pon f antes de la comilla de apertura y envuelve cualquier cosa en {}: una variable, una suma, incluso una llamada a método. Un dos puntos agrega formato, como :.2f para dos lugares decimales. Mucho más limpio que pegar cadenas juntas con +.
JunoFormateando salida con f-stringsf"..." coloca el resultado de cualquier expresión directamente en la cadena, sin str() necesario. Después de un dos puntos viene la especificación de formato: :.2f, :,, :>12 y compañía. Más limpio y rápido que la concatenación.
JunoFormateando salida con f-strings Cada {} llama al __format__ del valor, así que la especificación después del dos puntos significa lo que ese tipo decide. !r es la que recordar: muestra un valor de la forma en que lo escribirías, lo que hace que espacios finales y otras cosas invisibles se destaquen cuando estás depurando.

Obteniendo entrada del usuario

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

python
name = input("¿Cuál es tu nombre? ")
print(f"¡Hola, {name}!")

input() siempre devuelve una cadena, sin importar qué escriba el usuario. Escribe 42 y obtienes "42", no el número 42. Para hacer aritmética con él, convierte explícitamente:

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

¿Qué pasa si el usuario escribe algo que no puede convertirse? Python lanza un ValueError. Manejar eso apropiadamente se cubre en el capítulo Files and exceptions.

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

python
name = input("¿Cuál es tu nombre? ")
age = int(input("¿Cuántos años tienes? "))

Este patrón (recibir texto, convertir al tipo que necesitas) se aplica en todas partes donde llegan datos externos. int(), float(), y str() son las herramientas de conversión. Si la cadena no puede convertirse, Python lanza ValueError, cubierto en el capítulo Files and exceptions.

input() es un envoltorio delgado: escribe el mensaje a 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 la nueva línea final, y devuelve un str. Siempre es un str por diseño, porque Python no puede adivinar si "42" fue pensado como un entero, un flotante, o texto literal. Así que conviertes en el límite. Esta es la forma fundamental de la E/S de Python: los datos externos llegan como texto, y tu código decide su tipo en el punto de entrada.

python
name = input("Ingresa tu nombre: ")
score = float(input("Ingresa tu puntuación (0.0 a 1.0): "))

print(f"Name:  {name!r}")      # !r revela cualquier espaciado invisible
print(f"Score: {score:.1%}")
JunoObteniendo entrada del usuarioinput() muestra tu mensaje, espera una línea, y siempre la devuelve como una cadena, incluso si escriben un número. ¿Necesitas un número? Conviértelo tú mismo con int() o float() conforme entra, luego continúa con el tipo correcto.
JunoObteniendo entrada del usuarioinput() siempre devuelve un str, sin inferencia de tipo. Convierte en el límite con int() o float(), y espera un ValueError si el texto no se analiza. Ese patrón de recibir-luego-convertir aparece en todas partes donde llegan datos externos.
JunoObteniendo entrada 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 analice. La misma forma que en todos los otros lugares donde llegan datos externos.

Escribiendo a stderr

Por defecto, print() escribe a salida estándar: el flujo que aparece en la terminal y fluye hacia tuberías. Python también tiene error estándar, 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 stdout pasa. Stderr siempre llega a la terminal.

Escribir a stderr usa el argumento file de print(). Eso requiere importar sys, cubierto en el capítulo Modules. Por ahora, saber que los dos flujos existen y por qué son separados es suficiente.

En la práctica

Un cuestionario que se personaliza desde la entrada del usuario:

python
name = input("¿Cuál es tu nombre? ")
subject = input("¿Qué tema? ")

print(f"Bien, {name}. Iniciando tu cuestionario de {subject}.")
print("¡Buena suerte!")

Ambas entradas vuelven como cadenas y van directamente a los f-strings. Sin conversión necesaria porque las estás usando como texto, no como números.

Un convertidor 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 del usuario. La especificación :>12 mantiene las columnas alineadas sin importar cuántos dígitos tengan los números. Intenta ingresando 100 y -40: la salida se mantiene limpia de cualquier forma.

Usando !r para revelar exactamente qué Python recibió, útil cuando la salida se ve mal:

python
name = input("Ingresa tu nombre: ")
score = float(input("Ingresa tu puntuación (0.0 a 1.0): "))

print(f"Name:   {name!r}")
print(f"Score:  {score!r}")
print()
print(f"Result: {name}: {score:.1%}")

{name} y {name!r} se muestran idénticamente cuando la entrada es limpia. La diferencia aparece cuando hay espacios finales u otros caracteres invisibles. Acostumbrarse a usar !r durante la depuración hace que los valores inesperados sean visibles inmediatamente.