Algunos recursos necesitan limpieza: archivos que deben cerrarse, bloqueos que deben liberarse o conexiones que deben terminar. El problema aparece cuando hay varios caminos de salida o una excepción interrumpe el flujo.
Un context manager reúne la preparación y la limpieza en un mismo protocolo.
Explicar adquisición → uso → liberación y por qué with protege la limpieza incluso si algo falla.
El ejemplo cotidiano ya lo conoces: abrir, usar y cerrar un archivo
from io import StringIO
with StringIO("hola") as archivo:
contenido = archivo.read()
print(contenido)
print(archivo.closed)Dentro del with, el recurso está disponible. Al abandonar el bloque, se ejecuta su cierre aunque no hayas escrito close() manualmente.
La ventaja crece cuando el bloque puede terminar por un return o una excepción.
Ampliación: cómo se construye un context manager
Cuando usar with ya sea natural, puedes mirar debajo de la abstracción: @contextmanager ejecuta código antes de yield, pausa durante el bloque y usa finally para garantizar la limpieza. No necesitas construir uno propio para dominar la habilidad principal de esta lección.
La habilidad esencial es usar bien el ciclo de vida
Para un principiante, with es más importante que aprender a construir un context manager propio.
Reescribe la apertura manual usando with. La salida debe ser la misma, pero la limpieza debe quedar garantizada por la estructura del código.
ok
La salida aparecerá aquí.
Necesito una pista
- Usa un
with open(...)para escribir y otro para leer. - El archivo queda disponible con
as archivosolo dentro del bloque.
Ver una solución razonada
with open("mensaje.txt", "w", encoding="utf-8") as archivo:
archivo.write("ok")
with open("mensaje.txt", "r", encoding="utf-8") as archivo:
print(archivo.read())Ampliación: construir tu propio context manager
@contextmanager, yield y finally permiten crear un ciclo de vida propio. Déjalo como ampliación hasta que usar with te resulte natural.
from contextlib import contextmanager
@contextmanager
def recurso():
print("abrir")
try:
yield
finally:
print("cerrar")Lee cualquier with como un pequeño ciclo de vida
- Entrar: preparar o adquirir el recurso.
- Usar: ejecutar el bloque con el recurso disponible.
- Salir: liberar o restaurar lo que corresponda, incluso ante un fallo.
puedes explicar qué problema evita with sin mencionar archivos: garantizar una limpieza asociada a un bloque de uso.