Cómo trabajar con Archivos en Python: leer, escribir y modificar ficheros

D
DanisCh
• 19 min de lectura
Cómo trabajar con Archivos en Python: leer, escribir y modificar ficheros
Python

Los archivos son una de las formas más fundamentales de persistir datos entre ejecuciones de un programa. Los lees cuando cargas una configuración, los escribes cuando guardas resultados, los modificas cuando actualizas registros. Sin manejo de archivos, casi ningún programa del mundo real es posible.

Python tiene un sistema de manejo de archivos muy completo, Pythónico y fácil de aprender. En este artículo vas a dominar todo lo que necesitas: leer, escribir, modificar y gestionar archivos de texto, CSV y JSON, usando tanto la función clásica open() como el módulo moderno pathlib.

Si aún no dominas el manejo de errores en Python con try/except, te recomendamos leerlo antes — trabajar con archivos implica manejar excepciones como FileNotFoundError y PermissionError. Y si necesitas repasar las funciones en Python, también te vendrá bien como contexto.


La función open() — el punto de entrada

La función open() es la forma estándar de abrir un archivo en Python. Devuelve un objeto de archivo (file object) que permite leer, escribir o modificar el archivo.

# Sintaxis completa
open(
    file,           # ruta del archivo (string o Path)
    mode='r',       # modo de apertura (por defecto: lectura)
    encoding=None,  # codificación de texto (recomendado: 'utf-8')
    errors=None,    # cómo manejar errores de codificación
    newline=None    # manejo de saltos de línea
)

# Forma básica — solo los dos parámetros más comunes:
archivo = open("datos.txt", "r", encoding="utf-8")

Los modos de apertura — la tabla completa

Modo¿Qué hace?¿El archivo debe existir?Posición inicial
'r'Solo lectura✅ Sí (error si no existe)Principio
'w'Solo escritura — borra el contenido existente❌ No (lo crea si no existe)Principio (vacío)
'a'Append — añade al final sin borrar❌ No (lo crea si no existe)Final del archivo
'x'Creación exclusiva — falla si ya existe❌ No debe existirPrincipio (vacío)
'r+'Lectura y escritura✅ SíPrincipio
'w+'Lectura y escritura — borra el contenido❌ NoPrincipio (vacío)
'a+'Lectura y append❌ NoFinal (escritura)
'b'Modo binario (combinar: 'rb', 'wb')Depende del modo baseDepende del modo base
# Los modos más usados en la práctica:
open("archivo.txt", "r")   # leer texto
open("archivo.txt", "w")   # escribir (borra todo primero)
open("archivo.txt", "a")   # añadir al final
open("archivo.png", "rb")  # leer binario (imágenes, PDFs...)
open("archivo.png", "wb")  # escribir binario

El contexto with — siempre cierra el archivo

Antes de leer o escribir cualquier archivo, necesitas entender por qué el with es la forma correcta de hacerlo.

# ❌ Sin with — tienes que recordar cerrar el archivo manualmente
archivo = open("datos.txt", "r")
contenido = archivo.read()
# Si ocurre un error aquí, close() nunca se llama → archivo queda abierto
archivo.close()

# ✅ Con with — el archivo se cierra automáticamente al salir del bloque
# Incluso si ocurre una excepción dentro del with
with open("datos.txt", "r", encoding="utf-8") as archivo:
    contenido = archivo.read()
# ← archivo.close() se llama aquí automáticamente

# Con múltiples archivos en un solo with
with open("entrada.txt", "r") as entrada, open("salida.txt", "w") as salida:
    for linea in entrada:
        salida.write(linea.upper())

💡 Regla fundamental: Usa siempre el bloque with para abrir archivos. Nunca open() sin with a menos que tengas una razón muy específica.


Leer archivos — todos los métodos

read() — leer todo el contenido de una vez

# read() devuelve todo el contenido como un string
with open("poema.txt", "r", encoding="utf-8") as f:
    contenido = f.read()
    print(contenido)
    print(f"Total de caracteres: {len(contenido)}")

# read(n) — leer solo n caracteres
with open("poema.txt", "r", encoding="utf-8") as f:
    primeros_100 = f.read(100)   # los primeros 100 caracteres
    print(primeros_100)

readline() — leer línea por línea

# readline() lee una línea cada vez que se llama
with open("datos.txt", "r", encoding="utf-8") as f:
    primera_linea  = f.readline()   # "Nombre,Edad,Ciudad\n"
    segunda_linea  = f.readline()   # "Ana García,28,Madrid\n"
    tercera_linea  = f.readline()   # "Luis Pérez,35,Barcelona\n"
    linea_vacia    = f.readline()   # "" cuando llega al final

# Leer un archivo completo con readline en un bucle
with open("datos.txt", "r", encoding="utf-8") as f:
    while True:
        linea = f.readline()
        if not linea:   # string vacío = fin del archivo
            break
        print(linea.strip())  # strip() elimina el \n del final

readlines() — leer todas las líneas como lista

# readlines() devuelve una lista con cada línea como elemento
with open("ciudades.txt", "r", encoding="utf-8") as f:
    lineas = f.readlines()

print(lineas)
# ['Madrid\n', 'Barcelona\n', 'Sevilla\n', 'Valencia\n']
print(f"Total de líneas: {len(lineas)}")

# Limpiar los saltos de línea
lineas_limpias = [l.strip() for l in lineas]
print(lineas_limpias)
# ['Madrid', 'Barcelona', 'Sevilla', 'Valencia']

Iterar directamente — la forma más eficiente para archivos grandes

# La forma más Pythónica y eficiente — no carga todo en memoria
# Ideal para archivos grandes (logs, datasets, etc.)

with open("access.log", "r", encoding="utf-8") as f:
    for numero_linea, linea in enumerate(f, start=1):
        linea = linea.strip()
        if "ERROR" in linea:
            print(f"Línea {numero_linea}: {linea}")

# Para archivos grandes esta es la diferencia entre usar
# 10 MB de RAM (iteración) o 2 GB de RAM (readlines())

Comparativa de métodos de lectura

# read()      → todo el archivo como un string — simple pero usa mucha memoria
# readline()  → una línea a la vez — control total, verboso
# readlines() → lista de todas las líneas — cómodo pero carga todo en memoria
# iteración   → línea a línea sin cargar todo — eficiente para archivos grandes

Escribir archivos

write() — escribir texto

# write() escribe un string en el archivo
# Modo 'w' — borra el contenido existente y escribe desde cero
with open("resultado.txt", "w", encoding="utf-8") as f:
    f.write("Primera línea\n")
    f.write("Segunda línea\n")
    f.write("Tercera línea\n")

# ⚠️ write() no añade salto de línea automáticamente
# Debes añadir \n manualmente si quieres saltos de línea

# Modo 'a' — añade al final sin borrar el contenido existente
with open("log.txt", "a", encoding="utf-8") as f:
    from datetime import datetime
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    f.write(f"[{timestamp}] Aplicación iniciada\n")

writelines() — escribir múltiples líneas

# writelines() escribe una lista de strings
# IMPORTANTE: no añade \n entre elementos — debes incluirlos
ciudades = ["Madrid\n", "Barcelona\n", "Sevilla\n", "Valencia\n"]

with open("ciudades.txt", "w", encoding="utf-8") as f:
    f.writelines(ciudades)

# Equivalente más limpio con join:
ciudades = ["Madrid", "Barcelona", "Sevilla", "Valencia"]
with open("ciudades.txt", "w", encoding="utf-8") as f:
    f.write("\n".join(ciudades) + "\n")  # añade \n al final

print() dirigido a un archivo

# print() también puede escribir en archivos con el parámetro file=
with open("reporte.txt", "w", encoding="utf-8") as f:
    print("=== REPORTE DE VENTAS ===", file=f)
    print(f"Fecha: 2026-04-27", file=f)
    print(f"Total: $12,450.00", file=f)
    print("-" * 30, file=f)
# print() añade \n automáticamente — más cómodo que write() para texto formateado

Modo 'x' — creación exclusiva

# 'x' crea el archivo pero lanza FileExistsError si ya existe
# Útil cuando quieres asegurarte de no sobreescribir accidentalmente

try:
    with open("nuevo_archivo.txt", "x", encoding="utf-8") as f:
        f.write("Contenido del nuevo archivo")
    print("✅ Archivo creado")

except FileExistsError:
    print("❌ El archivo ya existe — no se sobreescribe")

Modificar archivos — las estrategias

No existe un modo de apertura que "edite" un archivo como un editor de texto. Para modificar archivos tienes varias estrategias según el caso:

Estrategia 1: Leer todo, modificar en memoria, escribir todo

# La estrategia más simple para archivos pequeños/medianos

def reemplazar_en_archivo(ruta, texto_viejo, texto_nuevo):
    """Reemplaza todas las ocurrencias de un texto en un archivo."""
    # 1. Leer todo el contenido
    with open(ruta, "r", encoding="utf-8") as f:
        contenido = f.read()

    # 2. Modificar en memoria
    contenido_modificado = contenido.replace(texto_viejo, texto_nuevo)

    # 3. Escribir el resultado (mode='w' sobreescribe el archivo)
    with open(ruta, "w", encoding="utf-8") as f:
        f.write(contenido_modificado)

    print(f"✅ Reemplazadas todas las ocurrencias de '{texto_viejo}'")

# Uso:
reemplazar_en_archivo("config.txt", "localhost", "192.168.1.100")

Estrategia 2: Archivo temporal (la más segura para producción)

import tempfile
import os
import shutil

def modificar_archivo_seguro(ruta_original, funcion_transformacion):
    """
    Modifica un archivo de forma segura usando un archivo temporal.
    Si algo falla, el archivo original no se modifica.
    """
    ruta = os.path.abspath(ruta_original)
    directorio = os.path.dirname(ruta)

    # Crear archivo temporal en el mismo directorio
    fd, ruta_temporal = tempfile.mkstemp(dir=directorio, suffix=".tmp")

    try:
        with os.fdopen(fd, 'w', encoding="utf-8") as temporal:
            with open(ruta, "r", encoding="utf-8") as original:
                for linea in original:
                    linea_modificada = funcion_transformacion(linea)
                    temporal.write(linea_modificada)

        # Reemplazar el original con el temporal (operación atómica en Linux)
        shutil.move(ruta_temporal, ruta)
        print(f"✅ Archivo modificado: {ruta}")

    except Exception as e:
        # Si algo falla, eliminar el temporal y preservar el original
        os.unlink(ruta_temporal)
        print(f"❌ Error — archivo original no modificado: {e}")
        raise

# Uso: añadir "→ " al inicio de cada línea
modificar_archivo_seguro(
    "lista.txt",
    lambda linea: f"→ {linea}"
)

# Uso: convertir todo a mayúsculas
modificar_archivo_seguro("notas.txt", str.upper)

Estrategia 3: Añadir líneas al final con 'a'

import datetime

def agregar_log(mensaje, archivo_log="app.log"):
    """Añade una entrada al archivo de log sin modificar lo existente."""
    timestamp = datetime.datetime.now().isoformat()
    with open(archivo_log, "a", encoding="utf-8") as f:
        f.write(f"[{timestamp}] {mensaje}\n")

agregar_log("Usuario ana@mail.com inició sesión")
agregar_log("Pedido #1042 procesado correctamente")
agregar_log("ERROR: conexión a BD fallida")

Gestión de rutas con pathlib — la forma moderna

pathlib (disponible desde Python 3.4) es la forma moderna y orientada a objetos de trabajar con rutas y archivos. Resuelve los problemas de portabilidad entre sistemas operativos y ofrece una API mucho más limpia que el antiguo módulo os.path.

from pathlib import Path

# ── Crear objetos Path ───────────────────────────────────────
ruta = Path("datos/usuarios.txt")
ruta_absoluta = Path("/home/usuario/proyectos/app/datos.txt")
directorio_actual = Path.cwd()        # directorio donde corre el script
home = Path.home()                     # directorio home del usuario

# ── Navegar por el sistema de archivos ───────────────────────
# El operador / construye rutas de forma multiplataforma (sin "/" hardcodeado)
ruta_datos = Path.cwd() / "datos" / "config.json"
ruta_log   = Path.home() / "logs" / "app.log"

# ── Propiedades de la ruta ───────────────────────────────────
ruta = Path("datos/usuarios/ana.json")
print(ruta.name)         # "ana.json"       ← nombre completo
print(ruta.stem)         # "ana"            ← nombre sin extensión
print(ruta.suffix)       # ".json"          ← extensión
print(ruta.suffixes)     # [".json"]        ← lista de extensiones
print(ruta.parent)       # "datos/usuarios" ← directorio padre
print(ruta.parts)        # ("datos", "usuarios", "ana.json")
print(ruta.resolve())    # ruta absoluta completa

# ── Verificaciones ───────────────────────────────────────────
ruta = Path("mi_archivo.txt")
print(ruta.exists())     # True/False — ¿existe?
print(ruta.is_file())    # True/False — ¿es un archivo?
print(ruta.is_dir())     # True/False — ¿es un directorio?

# ── Leer y escribir con pathlib ──────────────────────────────
ruta = Path("notas.txt")

# read_text() — lee todo el archivo como string (cierra automáticamente)
contenido = ruta.read_text(encoding="utf-8")

# write_text() — escribe un string (sobreescribe si existe)
ruta.write_text("Contenido nuevo del archivo\n", encoding="utf-8")

# read_bytes() / write_bytes() — para archivos binarios
imagen_bytes = Path("foto.png").read_bytes()
Path("foto_copia.png").write_bytes(imagen_bytes)

# ── Operaciones sobre archivos y directorios ─────────────────

# Crear directorios (con parents=True crea toda la jerarquía)
Path("datos/logs/2026").mkdir(parents=True, exist_ok=True)

# Renombrar / mover
Path("viejo.txt").rename("nuevo.txt")
Path("archivo.txt").rename(Path("otra_carpeta") / "archivo.txt")

# Copiar (pathlib no tiene copy directo, usa shutil)
import shutil
shutil.copy2("original.txt", "copia.txt")

# Eliminar
Path("temporal.txt").unlink()                 # eliminar archivo
Path("directorio_vacio").rmdir()              # eliminar directorio vacío
shutil.rmtree("directorio_con_contenido")    # eliminar directorio con todo

# Cambiar extensión
ruta = Path("informe.txt")
nueva_ruta = ruta.with_suffix(".md")   # informe.md
otra_ruta  = ruta.with_name("resumen.txt")  # resumen.txt

# ── Listar archivos ──────────────────────────────────────────
directorio = Path("datos")

# Listar todo lo que hay en el directorio
for elemento in directorio.iterdir():
    tipo = "📁" if elemento.is_dir() else "📄"
    print(f"{tipo} {elemento.name}")

# Buscar archivos con glob (recursivo con **)
archivos_py  = list(Path(".").glob("*.py"))           # .py en directorio actual
todos_py     = list(Path(".").rglob("*.py"))          # .py en todos los subdirectorios
archivos_txt = list(Path("datos").glob("**/*.txt"))   # .txt en subdirectorios de datos

print(f"Archivos Python: {len(todos_py)}")
for archivo in archivos_txt:
    print(f"  {archivo}")

pathlib vs os.path — la comparativa

import os
from pathlib import Path

# ── Construir rutas ──────────────────────────────────────────
# os.path (antiguo):
ruta = os.path.join("datos", "usuarios", "ana.json")

# pathlib (moderno):
ruta = Path("datos") / "usuarios" / "ana.json"  # más limpio y legible

# ── Obtener el directorio padre ──────────────────────────────
# os.path:
padre = os.path.dirname("/datos/usuarios/ana.json")

# pathlib:
padre = Path("/datos/usuarios/ana.json").parent

# ── Verificar si existe ──────────────────────────────────────
# os.path:
existe = os.path.exists("archivo.txt")

# pathlib:
existe = Path("archivo.txt").exists()

# ── Listar archivos .csv ──────────────────────────────────────
# os.path (verbose):
archivos = [
    os.path.join(dir_path, f)
    for f in os.listdir("datos")
    if os.path.isfile(os.path.join("datos", f)) and f.endswith(".csv")
]

# pathlib (limpio):
archivos = list(Path("datos").glob("*.csv"))

Archivos CSV — el formato de datos más universal

import csv
from pathlib import Path

# ── Escribir un CSV ──────────────────────────────────────────
datos = [
    ["nombre",      "email",              "edad", "ciudad"],
    ["Ana García",  "ana@ejemplo.com",    28,     "Madrid"],
    ["Luis Pérez",  "luis@ejemplo.com",   35,     "Barcelona"],
    ["María López", "maria@ejemplo.com",  24,     "Sevilla"],
]

with open("usuarios.csv", "w", newline="", encoding="utf-8") as f:
    # newline="" es importante en Windows para evitar líneas dobles
    escritor = csv.writer(f)
    escritor.writerows(datos)   # escribe todas las filas de una vez

# ── Leer un CSV ──────────────────────────────────────────────
with open("usuarios.csv", "r", encoding="utf-8") as f:
    lector = csv.reader(f)
    cabecera = next(lector)          # leer y saltar la cabecera
    print(f"Columnas: {cabecera}")

    for fila in lector:
        nombre, email, edad, ciudad = fila
        print(f"  {nombre} ({edad} años) — {ciudad}")

# ── DictReader / DictWriter — la forma más cómoda ────────────

# DictWriter: cada fila es un diccionario
campos = ["nombre", "email", "edad", "ciudad"]
productos = [
    {"nombre": "Ana García",  "email": "ana@mail.com",   "edad": 28, "ciudad": "Madrid"},
    {"nombre": "Luis Pérez",  "email": "luis@mail.com",  "edad": 35, "ciudad": "Barcelona"},
]

with open("usuarios_dict.csv", "w", newline="", encoding="utf-8") as f:
    escritor = csv.DictWriter(f, fieldnames=campos)
    escritor.writeheader()         # escribe la fila de cabecera
    escritor.writerows(productos)  # escribe todas las filas

# DictReader: cada fila es un diccionario con las claves de la cabecera
with open("usuarios_dict.csv", "r", encoding="utf-8") as f:
    lector = csv.DictReader(f)
    for fila in lector:
        # fila es un dict: {"nombre": "Ana García", "email": "...", ...}
        print(f"  {fila['nombre']} — {fila['ciudad']}")

# ── CSV con delimitador diferente (punto y coma, tabulación) ─
with open("datos_eu.csv", "r", encoding="utf-8") as f:
    lector = csv.reader(f, delimiter=";")  # formato europeo con ;
    for fila in lector:
        print(fila)

Archivos JSON — configuración y datos estructurados

import json
from pathlib import Path

# ── Escribir JSON ────────────────────────────────────────────
configuracion = {
    "app_name":  "Mi Aplicación",
    "version":   "2.1.0",
    "debug":     False,
    "database": {
        "host":   "localhost",
        "port":   5432,
        "name":   "mi_bd"
    },
    "allowed_hosts": ["localhost", "127.0.0.1", "mi-dominio.com"],
    "max_connections": 100
}

with open("config.json", "w", encoding="utf-8") as f:
    json.dump(
        configuracion,
        f,
        indent       = 2,           # formato legible con 2 espacios
        ensure_ascii = False,       # permite caracteres Unicode (acentos, ñ)
        sort_keys    = True         # ordena las claves alfabéticamente
    )

# ── Leer JSON ─────────────────────────────────────────────────
with open("config.json", "r", encoding="utf-8") as f:
    config = json.load(f)           # devuelve un dict de Python

print(f"App: {config['app_name']} v{config['version']}")
print(f"BD: {config['database']['host']}:{config['database']['port']}")
print(f"Hosts: {config['allowed_hosts']}")

# ── JSON a string y viceversa (sin archivo) ───────────────────
# json.dumps() → dict a string JSON
json_string = json.dumps({"nombre": "Ana", "edad": 28}, ensure_ascii=False)
print(json_string)  # '{"nombre": "Ana", "edad": 28}'

# json.loads() → string JSON a dict
datos = json.loads('{"nombre": "Ana", "edad": 28}')
print(datos["nombre"])  # "Ana"

# ── Con pathlib (más conciso para archivos simples) ───────────
# Leer
config = json.loads(Path("config.json").read_text(encoding="utf-8"))

# Escribir
Path("output.json").write_text(
    json.dumps(configuracion, indent=2, ensure_ascii=False),
    encoding="utf-8"
)

Archivos binarios — imágenes, PDFs y otros

# Los archivos binarios se abren con modo 'rb' (read binary) o 'wb' (write binary)
# No hay codificación — los datos son bytes puros

# Copiar un archivo binario (imagen, PDF, ejecutable...)
def copiar_archivo(origen, destino):
    with open(origen, "rb") as fuente:
        with open(destino, "wb") as copia:
            # Leer en bloques de 8KB — eficiente para archivos grandes
            while True:
                bloque = fuente.read(8192)
                if not bloque:
                    break
                copia.write(bloque)
    print(f"✅ Copiado: {origen} → {destino}")

copiar_archivo("foto.jpg", "foto_backup.jpg")

# Para archivos grandes, la forma más eficiente es shutil.copy2
import shutil
shutil.copy2("foto.jpg", "foto_backup.jpg")   # más rápido y preserva metadatos

# Leer los primeros bytes para identificar el tipo de archivo
def detectar_tipo_archivo(ruta):
    """Detecta el tipo de archivo leyendo su firma (magic bytes)."""
    firmas = {
        b'\xFF\xD8\xFF': 'JPEG',
        b'\x89PNG':      'PNG',
        b'%PDF':         'PDF',
        b'PK\x03\x04':  'ZIP/DOCX/XLSX',
        b'GIF87a':       'GIF',
        b'GIF89a':       'GIF',
    }
    with open(ruta, "rb") as f:
        cabecera = f.read(10)
    for firma, tipo in firmas.items():
        if cabecera.startswith(firma):
            return tipo
    return "Desconocido"

print(detectar_tipo_archivo("documento.pdf"))  # "PDF"
print(detectar_tipo_archivo("imagen.jpg"))     # "JPEG"

Manejo de errores con archivos

Trabajar con archivos implica gestionar errores que ocurren habitualmente: archivos que no existen, permisos insuficientes, disco lleno. Aplicando lo que ya sabes de manejo de errores en Python:

def leer_archivo_seguro(ruta, encoding="utf-8"):
    """Lee un archivo con manejo completo de errores."""
    try:
        with open(ruta, "r", encoding=encoding) as f:
            return f.read()

    except FileNotFoundError:
        print(f"❌ Archivo no encontrado: {ruta}")
        return None

    except PermissionError:
        print(f"❌ Sin permisos para leer: {ruta}")
        return None

    except UnicodeDecodeError:
        print(f"❌ Error de codificación en: {ruta} — prueba con encoding='latin-1'")
        # Reintentar con codificación alternativa
        try:
            with open(ruta, "r", encoding="latin-1") as f:
                return f.read()
        except Exception:
            return None

    except IsADirectoryError:
        print(f"❌ '{ruta}' es un directorio, no un archivo")
        return None

    except OSError as e:
        # Captura errores genéricos del SO: disco lleno, archivo roto, etc.
        print(f"❌ Error del sistema: {e}")
        return None

def escribir_archivo_seguro(ruta, contenido, encoding="utf-8"):
    """Escribe un archivo con manejo de errores y creación de directorios."""
    ruta_obj = Path(ruta)

    try:
        # Crear los directorios padre si no existen
        ruta_obj.parent.mkdir(parents=True, exist_ok=True)

        with open(ruta_obj, "w", encoding=encoding) as f:
            f.write(contenido)

        print(f"✅ Archivo guardado: {ruta}")
        return True

    except PermissionError:
        print(f"❌ Sin permisos para escribir en: {ruta}")
        return False

    except OSError as e:
        print(f"❌ Error al escribir: {e}")
        return False

Encoding — el problema que más archivos rompe

# El encoding por defecto depende del sistema operativo:
# Windows: cp1252 (o similar) ← causa problemas con acentos y ñ
# Linux/Mac: utf-8

# ❌ Sin encoding — comportamiento impredecible entre plataformas
with open("datos.txt", "r") as f:
    contenido = f.read()

# ✅ Siempre especifica el encoding — utf-8 es el estándar universal
with open("datos.txt", "r", encoding="utf-8") as f:
    contenido = f.read()

# Si el archivo tiene caracteres especiales y utf-8 falla:
# Prueba con "latin-1" (ISO-8859-1) o "cp1252" (Windows Western)
with open("archivo_antiguo.txt", "r", encoding="latin-1") as f:
    contenido = f.read()

# errors='ignore' — ignora caracteres que no se pueden decodificar
with open("datos_corruptos.txt", "r", encoding="utf-8", errors="ignore") as f:
    contenido = f.read()

# errors='replace' — reemplaza caracteres problemáticos con '?'
with open("datos_corruptos.txt", "r", encoding="utf-8", errors="replace") as f:
    contenido = f.read()

# Detectar el encoding de un archivo desconocido
# pip install chardet
import chardet
with open("misterioso.txt", "rb") as f:
    resultado = chardet.detect(f.read())
print(resultado)  # {'encoding': 'utf-8', 'confidence': 0.99}

Errores comunes al trabajar con archivos

❌ Olvidar el encoding y tener problemas con acentos

# Sin encoding en Windows: UnicodeDecodeError o caracteres corruptos
open("archivo.txt", "r")                     # ❌
open("archivo.txt", "r", encoding="utf-8")   # ✅

❌ No usar with y olvidar cerrar el archivo

f = open("datos.txt", "r")    # ❌ — si hay error, f nunca se cierra
contenido = f.read()
f.close()

with open("datos.txt", "r") as f:  # ✅ — cierre garantizado
    contenido = f.read()

❌ Abrir con 'w' cuando querías 'a'

# 'w' BORRA todo el contenido existente antes de escribir
with open("log.txt", "w") as f:  # ❌ borra los logs anteriores
    f.write("Nueva entrada\n")

with open("log.txt", "a") as f:  # ✅ añade al final
    f.write("Nueva entrada\n")

❌ Rutas hardcodeadas con barras que no funcionan en Windows

ruta = "datos/usuarios/ana.json"   # ❌ en Windows puede fallar
ruta = "datos\\usuarios\\ana.json" # ❌ no funciona en Linux/Mac

from pathlib import Path
ruta = Path("datos") / "usuarios" / "ana.json"  # ✅ multiplataforma

❌ Leer archivos grandes con read() o readlines()

# Un archivo de 5 GB cargado con read() consume 5 GB de RAM
with open("enorme.log", "r") as f:
    todo = f.read()  # ❌ puede agotar la memoria

# ✅ Iterar línea por línea — usa memoria mínima
with open("enorme.log", "r") as f:
    for linea in f:
        procesar_linea(linea)

Resumen: lo que aprendiste hoy

  • ✅ open(ruta, modo, encoding="utf-8") abre un archivo — usa siempre el bloque with
  • ✅ Modos clave: 'r' leer, 'w' escribir (borra), 'a' añadir, 'x' crear sin sobreescribir, 'b' binario
  • ✅ read() todo el archivo, readline() una línea, readlines() lista, iteración para archivos grandes
  • ✅ write() escribe un string, writelines() escribe una lista — ninguno añade \n automáticamente
  • ✅ Para modificar: leer todo → modificar en memoria → escribir todo, o usar archivo temporal para mayor seguridad
  • ✅ pathlib.Path es la forma moderna: rutas orientadas a objetos, multiplataforma con el operador /
  • ✅ read_text() y write_text() de pathlib simplifican operaciones comunes en una sola línea
  • ✅ glob() y rglob() buscan archivos por patrón de forma recursiva
  • ✅ Usa el módulo csv con DictReader/DictWriter para archivos CSV
  • ✅ Usa json.load()/json.dump() con ensure_ascii=False e indent=2 para JSON legible
  • ✅ Siempre especifica encoding="utf-8" — el encoding por defecto varía según el sistema operativo

🧪 ¿Tienes los fundamentos de Python bien sólidos?

Trabajar con archivos en Python es Python intermedio. Para aprovecharlo bien necesitas dominar funciones, manejo de excepciones, listas y diccionarios. Comprueba dónde estás:

👉 Test: Python Básico 👉 Test: Python Intermedio 

¿Ya trabajabas con archivos en Python o era la primera vez que lo veías? ¿Cuál parte te resultó más útil: pathlib, CSV, JSON o el manejo de encoding? Cuéntanos en los comentarios 👇 — respondemos todos. 🚀

Etiquetas: Manejo de Archivos

¿Te ha gustado esta entrada?

Compártela con tus compañeros para que también sigan aprendiendo.

Comunidad y Comentarios

0 COMENTARIOS

No hay comentarios todavía. Sé el primero en compartir tu opinión.

Escribe tu opinión
Respondiendo a