Los archivos son solo strings con una ruta
La mayoría de programas eventualmente necesitan leer o escribir un archivo — configuraciones, datos de usuario, logs, exportaciones CSV, cachés pequeños. Python mantiene esto simple con una sola función incorporada, open(), más un bloque with para asegurar que las cosas se cierren limpiamente.
Vamos a repasar los casos comunes.
Leer un archivo entero
La lectura más simple:
with open("notes.txt") as f:
contents = f.read()
print(contents)
open("notes.txt") abre el archivo para leer (el valor por defecto). El bloque with significa que Python cerrará el archivo cuando salgas del bloque — incluso si se lanza una excepción. Una vez cerrado, no puedes usar f; el texto vive en contents.
contents es un único string que contiene el archivo entero. Bien para archivos pequeños; mal para un log de 2 GB.
Leer línea a línea
Para archivos más grandes, itera en vez de leer todo en memoria:
with open("big.log") as f:
for line in f:
if "ERROR" in line:
print(line.strip())
Cada iteración produce una línea incluyendo el salto de línea final — por eso .strip() aparece tanto. Si quieres una lista de líneas, f.readlines() hace eso, pero normalmente la iteración directa es lo que quieres.
Escribir un archivo
Para escribir, pasa el modo como segundo argumento:
with open("output.txt", "w") as f:
f.write("first line\n")
f.write("second line\n")
Dos cosas a tener en cuenta:
"w"sobrescribe. Sioutput.txtya existe, su contenido desaparece en el momento en queopense ejecuta.- Tienes que añadir los saltos de línea tú.
f.write("hello")escribe exactamente esos cinco caracteres — sin salto de línea final.
Para añadir en vez de sobrescribir:
with open("output.txt", "a") as f:
f.write("another line\n")
También puedes meter varias líneas de una vez con writelines:
lines = ["a\n", "b\n", "c\n"]
with open("letters.txt", "w") as f:
f.writelines(lines)
Misma regla: tú pones los saltos de línea.
print a un archivo
print tiene un argumento file, que es una forma fácil de escribir sin los saltos de línea manuales:
with open("log.txt", "w") as f:
print("started", file=f)
print("finished", file=f)
Cada print escribe sus argumentos más un salto de línea final. Para salida informal, esta suele ser la forma más agradable.
Modo texto vs binario
Por defecto, open está en modo texto. Python decodifica bytes a strings (usando UTF-8 por defecto en plataformas modernas) y maneja la traducción de saltos de línea.
Para imágenes, PDFs, archivos compilados o cualquier cosa que no sea texto, abre en modo binario añadiendo "b" al modo:
with open("image.png", "rb") as f:
data = f.read()
print(len(data)) # número de bytes
with open("image_copy.png", "wb") as f:
f.write(data)
En modo binario, obtienes objetos bytes en vez de str, y Python no toca los finales de línea.
Especificar encoding
Para archivos de texto, sé explícito sobre el encoding. UTF-8 es casi siempre correcto en 2026:
with open("notes.txt", encoding="utf-8") as f:
contents = f.read()
Si estás tratando con archivos legacy de un entorno solo-Windows, también podrías ver cp1252 o latin-1. Adivinar mal te da caracteres corrompidos o un UnicodeDecodeError.
pathlib: la forma moderna de manejar paths
El módulo pathlib de la librería estándar te da una API más ergonómica que los strings crudos:
from pathlib import Path
path = Path("notes.txt")
# Lectura y escritura simples.
contents = path.read_text(encoding="utf-8")
path.write_text("new contents\n", encoding="utf-8")
# Construir paths sin preocuparte por / vs \.
data_dir = Path("data")
log_path = data_dir / "today.log"
print(log_path)
print(log_path.exists())
print(log_path.suffix) # ".log"
print(log_path.stem) # "today"
print(log_path.parent) # "data"
Path.read_text() y write_text() son atajos para el patrón with open(...) as f cuando solo quieres lecturas y escrituras de una sola vez. Para iteración línea a línea, sigues usando open o path.open().
Un pequeño ejemplo de principio a fin
Leer una lista de elementos de un archivo, filtrarlos y escribir el resultado en otro archivo:
from pathlib import Path
source = Path("items.txt")
destination = Path("filtered.txt")
items = source.read_text().splitlines()
kept = [item for item in items if item and not item.startswith("#")]
destination.write_text("\n".join(kept) + "\n")
print(f"Kept {len(kept)} items out of {len(items)}")
splitlines() es el compañero orientado a líneas de join. Parte por caracteres de salto de línea sin mantenerlos — útil cuando vas a volver a juntar las piezas de todas formas.
Cuando las cosas van mal
Abrir un archivo que no existe lanza FileNotFoundError. Intentar leer un archivo para el que no tienes permiso lanza PermissionError. Ambos son subclases de OSError, que a su vez es subclase de Exception — hablaremos de manejar excepciones apropiadamente en la siguiente página.
Por ahora, un adelanto rápido de cómo se ve el manejo de errores:
from pathlib import Path
path = Path("maybe.txt")
try:
contents = path.read_text()
except FileNotFoundError:
print("File doesn't exist — starting fresh.")
contents = ""
print(repr(contents))
Hábitos clave
- Usa siempre
with open(...)en vez deopencrudo + cierre manual. - Pasa siempre
encoding=para archivos de texto; UTF-8 por defecto. - Itera archivos grandes línea a línea; no los leas enteros con
.read(). - Para paths y patrones comunes de lectura/escritura, usa
pathlib— te ahorrará mucha gimnasia con strings.
A continuación: JSON. La mayoría de archivos de texto del mundo real que leas no son líneas planas — están estructurados, y JSON es la forma más común. Los mismos hábitos de with open(...) se trasladan directamente.
Preguntas frecuentes
¿Cómo leo un archivo en Python?
Usa open() con la sentencia with, que cierra el archivo automáticamente cuando termines. with open('file.txt') as f: contents = f.read() lee el archivo entero en un string. Para línea a línea, itera directamente sobre el objeto archivo: for line in f:.
¿Cuál es la diferencia entre los modos 'r', 'w' y 'a'?
'r' es read (el valor por defecto). 'w' es write — crea el archivo o lo trunca si existe. 'a' es append — añade al final del archivo sin borrar lo que hay. Añade 'b' para modo binario o '+' para lectura+escritura.
¿Por qué usar with open en vez de open a secas?
with open en vez de open a secas?La sentencia with garantiza que el archivo se cierra incluso si ocurre un error a mitad. Sin with, te toca llamar a .close() tú mismo y acordarte de hacerlo en los caminos de error. with es más seguro y menos código.