Sentencia with en Python: archivos seguros y contextos

Actualizado el: 11/07/2026
Tempo de leitura: 4 minutos
Uso do with para abrir arquivos com segurança em Python

La sentencia with en Python administra recursos que deben abrirse y cerrarse correctamente. Su uso más conocido es trabajar con archivos, pero también se aplica a conexiones, bloqueos, transacciones y objetos temporales que implementan el protocolo de context manager.

El principal beneficio es que la limpieza ocurre incluso cuando se produce una excepción. Esto reduce archivos abiertos, bloqueos olvidados y código repetido dentro de bloques try y finally.

Abrir un archivo sin with

file = open("notes.txt", encoding="utf-8")
content = file.read()
file.close()

Si read() genera un error, close() puede no ejecutarse. Una versión segura necesitaría:

file = open("notes.txt", encoding="utf-8")

try:
    content = file.read()
finally:
    file.close()

with expresa este patrón de forma más clara.

Leer un archivo con with

with open("notes.txt", encoding="utf-8") as file:
    content = file.read()

print(content)

Cuando termina el bloque indentado, Python cierra el archivo. La variable puede seguir existiendo, pero el recurso ya no admite operaciones.

La referencia oficial de la sentencia with explica su comportamiento y equivalencia con try/finally.

Modos de apertura

  • r: lectura.
  • w: escritura, reemplazando el archivo.
  • a: añadir al final.
  • x: crear y fallar si ya existe.
  • rb y wb: modos binarios.
  • +: lectura y escritura.

La guía de archivos de texto en Python explica lectura, escritura, append y codificación.

Escribir texto

with open(
    "report.txt",
    "w",
    encoding="utf-8",
) as file:
    file.write("Informe mensual\n")
    file.write("Estado: completado\n")

El modo w borra el contenido anterior. Para conservarlo, utiliza a:

with open(
    "activity.log",
    "a",
    encoding="utf-8",
) as file:
    file.write("Nueva ejecución\n")

Utilizar print() con un archivo

with open(
    "summary.txt",
    "w",
    encoding="utf-8",
) as file:
    print("Resumen", file=file)
    print("Total: 120", file=file)

print() añade saltos de línea y admite sep y end. La guía de print() en Python presenta más opciones.

Leer línea por línea

Para archivos grandes, no cargues todo con read():

with open("events.log", encoding="utf-8") as file:
    for line_number, line in enumerate(file, start=1):
        cleaned = line.rstrip()
        print(line_number, cleaned)

El archivo funciona como iterable y entrega una línea cada vez. Este patrón utiliza poca memoria.

Leer una línea o todas

with open("notes.txt", encoding="utf-8") as file:
    first_line = file.readline()
    remaining = file.readlines()

readlines() crea una lista con todas las líneas restantes. Para archivos grandes, la iteración suele ser mejor.

Trabajar con pathlib

from pathlib import Path

path = Path("data") / "report.txt"

with path.open("w", encoding="utf-8") as file:
    file.write("Contenido seguro\n")

La guía de pathlib en Python explica cómo construir rutas portables y recorrer carpetas.

Archivos CSV

import csv

with open(
    "sales.csv",
    encoding="utf-8",
    newline="",
) as file:
    reader = csv.DictReader(file)

    for row in reader:
        print(row["product"], row["amount"])

El argumento newline="" permite que el módulo CSV gestione correctamente los saltos. La guía de CSV en Python explica lectores, escritores y delimitadores.

Abrir varios archivos a la vez

with (
    open("source.txt", encoding="utf-8") as source,
    open("destination.txt", "w", encoding="utf-8") as destination,
):
    for line in source:
        destination.write(line.upper())

Ambos recursos se cierran al finalizar. Si la segunda apertura falla, el primer recurso también se libera.

Manejar errores

from pathlib import Path

path = Path("config.json")

try:
    with path.open(encoding="utf-8") as file:
        content = file.read()
except FileNotFoundError:
    print("El archivo no existe")
except PermissionError:
    print("No hay permisos para leerlo")

with garantiza la limpieza, pero no oculta el error. La guía de try y except en Python explica cómo capturar excepciones específicas.

Qué es un context manager

Un context manager implementa dos métodos:

  • __enter__(): prepara el recurso y devuelve el valor asignado después de as.
  • __exit__(): ejecuta la limpieza al salir.
class ManagedResource:
    def __enter__(self):
        print("Abriendo recurso")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("Cerrando recurso")
        return False


with ManagedResource() as resource:
    print("Utilizando recurso")

Devolver False permite que una excepción continúe. Devolver True la suprime, lo que debe hacerse solamente de forma deliberada.

Crear context managers con contextlib

from contextlib import contextmanager
from time import perf_counter


@contextmanager
def timer(label):
    start = perf_counter()

    try:
        yield
    finally:
        elapsed = perf_counter() - start
        print(f"{label}: {elapsed:.4f} segundos")


with timer("Procesamiento"):
    total = sum(range(1_000_000))

El código anterior a yield prepara el contexto. El bloque finally garantiza la limpieza.

La documentación oficial de contextlib incluye contextmanager, closing, suppress y ExitStack.

Bloqueos con with

from threading import Lock

lock = Lock()

with lock:
    update_shared_data()

El bloqueo se libera incluso si la función genera una excepción.

Conexiones y transacciones

import sqlite3

with sqlite3.connect("app.db") as connection:
    connection.execute(
        "INSERT INTO events(message) VALUES (?)",
        ("Aplicación iniciada",),
    )

El comportamiento exacto de commit, rollback y cierre depende de la biblioteca. Consulta su documentación; no supongas que todos los objetos hacen lo mismo.

Archivos temporales

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "report.txt"
    path.write_text(
        "datos temporales",
        encoding="utf-8",
    )
    print(path.read_text(encoding="utf-8"))

Al salir, el directorio temporal se elimina. Este patrón es útil en pruebas y conversiones.

ExitStack para recursos dinámicos

Cuando la cantidad de archivos no se conoce de antemano:

from contextlib import ExitStack

paths = ["a.txt", "b.txt", "c.txt"]

with ExitStack() as stack:
    files = [
        stack.enter_context(
            open(path, encoding="utf-8")
        )
        for path in paths
    ]

    contents = [file.read() for file in files]

ExitStack registra cada recurso y los cierra en orden inverso.

Ejemplo: copiar y transformar registros

from pathlib import Path

source_path = Path("raw.txt")
target_path = Path("clean.txt")

with (
    source_path.open(encoding="utf-8") as source,
    target_path.open("w", encoding="utf-8") as target,
):
    for line in source:
        cleaned = " ".join(line.strip().split())

        if not cleaned:
            continue

        target.write(cleaned + "\n")

Este ejemplo procesa línea por línea, normaliza espacios y mantiene ambos archivos bajo administración segura.

Errores frecuentes

  • Abrir texto sin especificar UTF-8.
  • Usar w cuando se quería añadir.
  • Intentar utilizar el archivo fuera del bloque.
  • Capturar excepciones demasiado amplias.
  • Suponer que todo context manager cierra una conexión.
  • Suprimir errores devolviendo True sin necesidad.
  • Cargar archivos enormes con read().

With frente a try/finally

with no reemplaza conceptualmente a try/finally; lo encapsula mediante un protocolo reutilizable. Utiliza with cuando el objeto ofrezca un context manager. Crea uno propio cuando exista una preparación y una limpieza que deban permanecer siempre juntas.

Conclusión

La sentencia with hace explícito el ciclo de vida de un recurso. Utilízala para archivos, bloqueos, conexiones y objetos temporales. Domina los modos de apertura, la codificación, el manejo de excepciones y el protocolo __enter__/__exit__. El resultado será código más corto, seguro y fácil de revisar.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Logo do Python com as palavras global e local
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Alcance de variables en Python: entiende la regla LEGB

    Entiende el alcance de variables en Python con la regla LEGB, global, nonlocal, closures, sombreado, mutabilidad y UnboundLocalError.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Operações matemáticas usando o módulo math em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Módulo math en Python: operaciones matemáticas esenciales

    Aprende el módulo math en Python: raíces, potencias, redondeos, trigonometría, logaritmos, constantes, isclose y ejemplos prácticos.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Geração de números aleatórios seguros usando secrets em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Módulo secrets en Python: números y tokens seguros

    Aprende secrets en Python para generar contraseñas, códigos y tokens seguros con randbelow, choice, token_hex, token_urlsafe y compare_digest.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Uso do operador walrus para atribuições inline em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Operador walrus en Python: guía con ejemplos

    Aprende el operador walrus := en Python: condiciones, while, comprensiones, lectura por bloques, regex, alcance y buenas prácticas.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Uso da função zip para combinar listas em Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    zip() en Python: combina listas e iterables correctamente

    Aprende zip() en Python para combinar listas, crear diccionarios, usar strict, zip_longest, desempaquetar valores y evitar pérdidas silenciosas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Uso do módulo time para controlar tempo em scripts Python
    Fundamentos
    Foto de perfil de Leandro Hirt da Academify

    Módulo time en Python: pausas, timestamps y rendimiento

    Aprende el módulo time en Python: timestamps, sleep, monotonic, perf_counter, struct_time, strftime y buenas prácticas para medir tiempo.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026