Pregunta 1¿Qué significa el segundo argumento "r" en with open("data/notes.txt", "r") as f:?
Entrada/salida de archivos — Lee y escribe seguro con with open()
Aprende la entrada/salida de archivos en Python. with open() con cierre automático, diferencias entre read / readlines / readline, modos w / a y el patrón leer-procesar-escribir que guarda en otro archivo — práctica incluida.
La mayoría de los datos con los que trabajan los programas viven en disco como archivos. Leer una lista de tareas, añadir a un log, cargar una configuración — todas son operaciones del día a día.
En Python, with open() te deja hacer esto en una sola unidad sintáctica segura. Este artículo cubre la forma básica de with open(), los tres métodos de lectura (read / readlines / readline), la escritura (w) y la adición (a), y el manejo de rutas con directorios — ejecutando código real contra archivos.
with open() abre y cierra archivos de forma segura
Abrir un archivo es una operación que hace que el SO retenga un recurso, y una vez abierto, debes cerrarlo. Olvidarlo provoca agotamiento de descriptores de archivo, o que los datos a escribir queden atrapados en buffers y nunca lleguen al disco.
open() hace que el SO asigne un descriptor de archivo (FD). Hasta close(), el FD queda retenido y las escrituras se quedan en buffer, sin volcar. Olvidar cerrar es una fuga grave de recursos.¿Qué es un descriptor de archivo (FD)?
FD (file descriptor) es el ID entero que el SO asigna a cada archivo abierto en este momento. Cada open() reparte un nuevo FD; close() lo devuelve al SO. El SO impone un límite máximo por proceso (en Linux, alrededor de 1.024 por defecto). Al alcanzar ese límite, los nuevos open() empiezan a fallar con OSError: Too many open files. El peligro de olvidar cerrar es exactamente este: retener para siempre un recurso finito.
Escribe la forma with open(path, mode) as f: y el archivo se cierra automáticamente en el momento en que sales del bloque, así que es imposible cometer el error. La f en as f es la variable que recibe el objeto archivo; dentro del bloque with, lees y escribes a través de f.
Las rutas usan barras inclinadas / para separar directorios. open("data/tasks.txt", "r") abre tasks.txt dentro de la carpeta data bajo el directorio actual. Incluso en Windows, la convención de Python usa / — internamente se traduce según el SO.
with abre el archivo y lo enlaza a as f. Al salir del bloque — normal o por excepción — close() corre automáticamente.Lectura — read / readlines / readline
Para leer un archivo, usa r (read) como segundo argumento de open(path, "r"). El objeto archivo devuelto tiene tres métodos de lectura para necesidades distintas.
- f.read() — lee el archivo completo como una sola cadena.
- f.readlines() — lo lee como una lista de líneas (cadenas).
- f.readline() — lee una línea. Llamadas repetidas avanzan a la siguiente línea; una cadena vacía "" señala fin de archivo.
# Obtener todo el archivo como una sola cadena
with open("data/tasks.txt", "r") as f:
content = f.read()
print(type(content)) # <class 'str'>
# Obtener una lista de líneas
with open("data/tasks.txt", "r") as f:
lines = f.readlines()
print(type(lines)) # <class 'list'>
# Obtener una línea cada vez (siguiente llamada -> siguiente línea)
with open("data/tasks.txt", "r") as f:
first = f.readline() # "Escribir el informe\n"
second = f.readline() # "Responder correos\n"
A partir de aquí, la consola corre en un sistema de archivos virtual (VFS) en el navegador
La consola de la derecha es un sistema de archivos virtual en el navegador — los archivos como data/tasks.txt ya están preparados para ti. Para ejecutar el mismo código en tu PC local, crea una carpeta data/ junto a tu archivo Python (por ejemplo, main.py) y coloca tasks.txt dentro antes de ejecutar. La sintaxis de la ruta ("data/tasks.txt" con /) es idéntica al Python real.
Cuando el archivo es un registro por línea (CSV sin cabecera, una lista separada por saltos de línea, líneas de log), f.readlines() es conveniente. Devuelve una lista de cadenas, una por línea, y cada elemento conserva el \n final.
Imprimirla directamente produce doble interlineado, así que el patrón estándar es aplicar .rstrip("\n") para quitar el salto final.
¿Archivos grandes? Lee línea a línea — readline y la morsa
f.read() y f.readlines() cargan el archivo entero en memoria. Eso está bien para archivos del tamaño de una configuración, pero un log de servidor de varios GB puede romper el programa al quedarse sin memoria.
f.readline() carga solo una línea cada vez, así que el uso de memoria se queda en lo que ocupa una línea. Cuando readline() alcanza el fin de archivo, devuelve la cadena vacía "", que usas como condición de salida del bucle.
"" para indicar al bucle que pare.# Estilo clásico: sale al recibir cadena vacía
with open("data/log.txt", "r") as f:
while True:
line = f.readline()
if not line: # cadena vacía = EOF
break
print(line.rstrip())
El operador morsa := escribe lo mismo en una línea menos
Python 3.8 introdujo el operador morsa (:=), que te permite asignar y comprobar dentro de una expresión. Escribir while line := f.readline(): significa «pon el resultado de readline() en line y sigue iterando mientras no esté vacío» — todo el bucle en una línea.
Escritura — modo w y modo a
Escribir es solo open() con otro segundo argumento. Dos modos cargan el peso práctico.
- "w" (write) — crear nuevo o sobrescribir. El contenido existente queda destruido.
- "a" (append) — añadir al final. El contenido existente se mantiene.
También existen dos métodos de escritura. f.write(s) escribe la cadena s directamente; f.writelines(lst) escribe una lista de cadenas de una sola vez. Si la ruta incluye una carpeta, el archivo se crea dentro (la carpeta debe existir ya).
# modo w: escribe cadenas una a una
with open("data/done.txt", "w") as f:
f.write("Escribir el informe\n")
f.write("Responder correos\n")
# modo w: escribe una lista de golpe con writelines
with open("data/done.txt", "w") as f:
f.writelines(["Escribir el informe\n", "Responder correos\n", "Asistir a la reunión\n"])
# modo a: añade al final
with open("data/done.txt", "a") as f:
f.write("Hacer las compras\n")
Los saltos de línea \n no se añaden automáticamente
A diferencia de print(), ni f.write() ni f.writelines() añaden saltos de línea por ti. Llamar f.write("Hola") dos veces deja HolaHola en el archivo. Inserta \n explícitos dondequiera que realmente quieras un salto de línea.
Yendo más allá — Analiza un archivo y guarda el resultado en otro
Uno de los patrones más comunes en el trabajo real es leer un archivo de entrada, hacer algún análisis y escribir el resultado en otro archivo aparte. Solo usa open() dos veces — una con "r", otra con "w". El estilo más limpio es poner entrada → proceso → salida en tres bloques with separados.
# Analiza data/log.txt y guarda el resultado en data/log_summary.txt
# (1) Entrada: lee el log como una lista de líneas
with open("data/log.txt", "r") as src:
lines = src.readlines()
# (2) Proceso: cuenta líneas, captura primera/última entrada
total = len(lines)
first = lines[0].rstrip()
last = lines[-1].rstrip()
summary = f"count: {total}\nfirst: {first}\nlast: {last}\n"
# (3) Salida: escribe en otro archivo distinto
with open("data/log_summary.txt", "w") as dst:
dst.write(summary)
print("Saved analysis to data/log_summary.txt")
encoding="utf-8" es el estándar para codificación de texto
En Python real, sueles escribir open(path, "r", encoding="utf-8") para especificar la codificación explícitamente. Intentar leer un archivo Shift-JIS como UTF-8 lanza UnicodeDecodeError, y al revés produce mojibake silencioso. El estándar mundial es UTF-8 — escribe los archivos nuevos en UTF-8 por defecto. El entorno del navegador codifica internamente UTF-8 por lo que omitir encoding= funciona aquí, pero hazlo costumbre cuando escribas scripts locales.
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2Cuando llamas a f.readline() repetidamente y el archivo termina, ¿qué valor vuelve?
Pregunta 3Si data/done.txt ya tiene contenido y abres con with open("data/done.txt", "w") as f:, ¿qué pasa con el contenido existente?