Puede que ya conozcas la sentencia with, una forma concisa de gestionar recursos en Python. Pero, ¿te has preguntado alguna vez cómo funciona por dentro? La fuerza de la palabra clave with viene de los gestores de contexto.
Los gestores de contexto son un patrón de diseño fundamental en Python que aporta una forma estructurada de gestionar recursos. Garantizan que los recursos se adquieran, se usen correctamente y, por último, se liberen o limpien, incluso cuando hay errores o excepciones.
Esto es especialmente importante al trabajar con recursos como ficheros, conexiones de red o manejadores de bases de datos. Gracias a los gestores de contexto, podemos escribir código más limpio y fiable, sin preocuparnos por olvidar cerrar un archivo o liberar un bloqueo.
En este tutorial, iremos más allá de los gestores de contexto que ofrece Python por defecto y aprenderemos a escribir los nuestros.
Entender los gestores de contexto en Python
Bajo el capó, los gestores de contexto son objetos que definen dos métodos especiales: __enter__ y __exit__. El método __enter__ se llama al entrar en el bloque with y su valor de retorno se asigna a una variable dentro de ese bloque. El método __exit__, por su parte, se llama cuando se sale del bloque with, tanto si termina con normalidad como si lo hace con una excepción.
Esta estructura garantiza un manejo correcto de los recursos. Veamos algunos gestores de contexto integrados en Python para entenderlo mejor:
Aquí, open('file.txt', 'r') actúa como gestor de contexto. Al entrar en el bloque with, se llama al método enter del objeto archivo, se abre el fichero y se asigna a la variable file. Después puedes usar file.read() para acceder a su contenido.
A continuación, se garantiza que el método __exit__ del objeto archivo se llame al salir del bloque with, incluso si se produce una excepción. Este método se encarga de cerrar el archivo, evitando dejar descriptores abiertos por ahí.
2. Bloqueo de hilos
Más allá de los archivos, los gestores de contexto también pueden usarse para la sincronización de hilos con threading.Lock():
import threading
lock = threading.Lock()with lock:# Sección críticaprint("This code is executed under lock protection.")Con la tecnología de
Aquí, lock es un objeto threading.Lock, otro gestor de contexto. Al entrar en el bloque with, el método __enter__ adquiere el bloqueo, garantizando que solo un hilo pueda ejecutar la sección crítica a la vez. Finalmente, el método __exit__ libera el bloqueo al salir del bloque with, permitiendo continuar a otros hilos.
3. Conexiones a bases de datos
De forma similar, los gestores de contexto pueden gestionar conexiones a bases de datos:
import sqlite3
with sqlite3.connect('database.db')as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM table")
rows = cursor.fetchall()Con la tecnología de
La llamada sqlite3.connect('database.db') es un gestor de contexto. Al entrar en el bloque with se establece la conexión a la base de datos y se asigna a connection. Después puedes usar un cursor para interactuar con la base. El método __exit__ garantiza que la conexión se cierre al salir del bloque with, evitando fugas de recursos.
4. Sockets de red
Los gestores de contexto incluso pueden encargarse de la comunicación de red:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM)as s:
s.connect(('localhost',8080))
s.sendall(b'Hello, world')
data = s.recv(1024)Con la tecnología de
Aquí, socket.socket(socket.AF_INET, socket.SOCK_STREAM) crea un objeto socket que actúa como gestor de contexto. El método __enter__ crea el socket y, dentro del bloque with, puedes conectar, enviar y recibir datos. El método __exit__ garantiza que el socket se cierre correctamente al finalizar.
5. Exploración de directorios
En este caso, os.scandir('.') permite iterar por las entradas de un directorio:
with os.scandir('.')as entries:for entry in entries:print(entry.name)Con la tecnología de
os.scandir('.') actúa aquí como gestor de contexto. El método __enter__ abre el escaneo del directorio y puedes iterar por las entradas dentro del bloque with. El método __exit__ limpia el escaneo al salir.
Como ves, la sentencia with, impulsada por los gestores de contexto, simplifica la gestión de recursos al encargarse automáticamente de su asignación y liberación.
Crear gestores de contexto personalizados en Python
Veamos ahora cómo escribir tus propios gestores para tener un control más fino sobre la gestión de recursos.
Hay dos enfoques principales para escribir gestores de contexto personalizados: basados en clases y basados en funciones.
Enfoque basado en clases
El enfoque basado en clases es el método más estructurado y flexible para escribir gestores de contexto. Aquí defines una clase que implementa los métodos especiales __enter__ y __exit__.
Veamos un ejemplo de una clase Timer que mide el tiempo de ejecución:
import time
classTimer:def__enter__(self):
self.start_time = time.time()return self
def__exit__(self, exc_type, exc_value, traceback):
self.end_time = time.time()
elapsed_time = self.end_time - self.start_time
print(f"Elapsed time: {elapsed_time} seconds")# Example usageif __name__ =="__main__":with Timer()as timer:# Code block to measure the execution time
time.sleep(2)# Simulate some time-consuming operation
Elapsed time:2.002082347869873 seconds
Con la tecnología de
Aquí, la clase Timer define el método __enter__ para capturar la hora de inicio al entrar en el bloque with. Devuelve self para permitir el acceso al objeto dentro del bloque. El método __exit__ calcula el tiempo transcurrido al salir del bloque with y lo imprime.
Enfoque basado en funciones
Si prefieres algo más conciso, aunque quizá menos flexible, el enfoque basado en funciones puede ser una buena opción. Aquí usas el decorador contextmanager del módulo contextlib para convertir una función en gestor de contexto.
Veamos cómo funciona:
import time
from contextlib import contextmanager
@contextmanagerdeftimer():
start_time = time.time()yield
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Elapsed time: {elapsed_time} seconds")# Example usageif __name__ =="__main__":with timer():
time.sleep(2)
Elapsed time:2.0020740032196045 seconds
Con la tecnología de
El decorador @contextmanager transforma la función timer en un gestor de contexto. Dentro de la función se captura start_time, y la sentencia yield pausa la ejecución para que se ejecute el código del bloque with.
Por último, la funcionalidad equivalente a __exit__ se consigue capturando la hora final e imprimiendo el tiempo transcurrido.
En esencia, escribes la lógica de __enter__ antes de la palabra clave yield, mientras que la lógica de __exit__ va después. Ambos enfoques logran lo mismo; la elección depende de tu preferencia por la estructura y la legibilidad.
Ejemplos prácticos de gestores de contexto
Ahora que sabes escribir gestores de contexto personalizados en Python, veamos algunos ejemplos prácticos donde pueden ser muy útiles.
Gestionar operaciones con archivos
Las operaciones con archivos son habituales en muchas aplicaciones. Ya sea leer o escribir, una buena gestión garantiza la integridad de los datos y la eficiencia de los recursos. Consideremos un escenario en el que queremos escribir texto a un archivo usando un gestor de contexto personalizado.
classFileManager:def__init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file=Nonedef__enter__(self):
self.file=open(self.filename, self.mode)return self.filedef__exit__(self, exc_type, exc_value, traceback):if self.file:
self.file.close()# Example usageif __name__ =="__main__":with FileManager("example.txt","w")asfile:file.write("Hello, world!\n")Con la tecnología de
En este ejemplo, definimos una clase FileManager que imita la función open de Python y gestiona las operaciones con archivos. Desglosando cada método:
__init__(self, filename, mode): es el constructor de la clase. Inicializa el objeto FileManager con el nombre de archivo y el modo, que especifican qué archivo abrir y en qué modo (por ejemplo, lectura, escritura, anexar).
__enter__(self): se llama al entrar en el bloque with. Abre el archivo indicado por filename en el modo indicado por mode. El objeto fichero abierto se asigna a self.file y se devuelve para usarse dentro del bloque with.
__exit__(self, exc_type, exc_value, traceback): se llama al salir del bloque with, tanto si se produjo una excepción como si no. Garantiza que el archivo se cierre correctamente llamando a self.file.close() si self.file no es None. Así se evitan fugas de recursos y se asegura la limpieza.
Si inspeccionas el contenido de example.txt tras ejecutar el código anterior, verás el texto escrito:
Por supuesto, la ventaja de la clase FileManager es que puedes implementar cualquier lógica personalizada para trabajar con archivos. Por ejemplo, puedes modificarla para que lleve un registro en un fichero de texto de qué archivos se abren o cierran.
De nuevo, esto imita la función sqlite3.connect, pero puede mejorarse añadiendo lógica personalizada de gestión de la base de datos. Comprobemos si el gestor funciona con algunas funciones de ejemplo:
# Example usagedefcreate_table():with DatabaseConnection("example.db")as connection:
cursor = connection.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
username TEXT,
email TEXT)""")definsert_data(username, email):with DatabaseConnection("example.db")as connection:
cursor = connection.cursor()
cursor.execute("INSERT INTO users (username, email) VALUES (?, ?)",(username, email))
connection.commit()deffetch_data():with DatabaseConnection("example.db")as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM users")return cursor.fetchall()if __name__ =="__main__":
create_table()
insert_data("john_doe","[email protected]")
insert_data("jane_doe","[email protected]")
users = fetch_data()print("Users in the database:")for user in users:print(user)
Users in the database:(1,'john_doe','[email protected]')(2,'jane_doe','[email protected]')(3,'john_doe','[email protected]')(4,'jane_doe','[email protected]')Con la tecnología de
Podemos escribir un código mucho más mantenible separando las operaciones de base de datos en funciones y usando el gestor personalizado que acabamos de crear.
Temas avanzados sobre gestores de contexto en Python
En esta sección, hablaremos de temas avanzados relacionados con los gestores de contexto en Python. Entre ellos, el manejo de errores y el anidamiento de gestores de contexto.
Manejo de errores
El manejo de errores es esencial en programación, y los gestores de contexto en Python facilitan gestionar errores dentro de operaciones de gestión de recursos.
En el ejemplo de la clase FileManager, el manejo de errores puede implementarse dentro del método __exit__ para asegurar la limpieza incluso si ocurre una excepción. Por ejemplo, si se produce un error al escribir en el archivo (dentro del bloque with), aun así queremos asegurarnos de que el archivo se cierra para evitar fugas de recursos. Podemos modificar __exit__ así:
def__exit__(self, exc_type, exc_value, traceback):if self.file:
self.file.close()if exc_type isnotNone:print(f"An error occurred: {exc_value}")Con la tecnología de
Aquí, primero cerramos el archivo con self.file.close() para asegurar la limpieza. Luego comprobamos si ocurrió una excepción (exc_type is not None). Si es así, imprimimos un mensaje de error para dar contexto de lo sucedido.
Aquí:
exc_type es la clase de la excepción, como AttributeError o IndexError.
exc_value es la instancia de la excepción con su mensaje.
traceback es el traceback completo del error.
Ejecutemos la clase FileManager con un código incorrecto a propósito:
with FileManager("example.txt","r")asfile:# Simular un error de ejemplo
content =file.read()print(content[150])
An error occurred: string index out of rangeCon la tecnología de
Así, para implementar lógica personalizada al manejar excepciones en tus gestores, aquí tienes un flujo de trabajo de ejemplo que puedes seguir:
def__exit__(self, exc_type, exc_value, traceback):# Realizar limpieza...# Gestionar la excepciónifisinstance(exc_value, AttributeError):# Gestionar AttributeError aquíprint(f"Exception message: {exc_value}")# Gestionar otra excepciónelifisinstance(exc_value, AnotherError):...Con la tecnología de
Anidar gestores de contexto
Anidar gestores de contexto te permite gestionar varios recursos a la vez, cada uno con su propio gestor, dentro de una sola sentencia with. Esto es especialmente útil en operaciones complejas que implican múltiples recursos. Veamos cómo anidarlos en nuestros ejemplos.
Imagina que quieres abrir un archivo y realizar operaciones de base de datos dentro del mismo contexto. Por ejemplo, introducir el contenido de un CSV como filas de una base de datos. Podemos conseguirlo anidando los gestores FileManager y DatabaseConnection dentro de una sola sentencia with:
if __name__ =="__main__":with FileManager("example.txt","w")asfile, DatabaseConnection("example.db")as connection:...Con la tecnología de
En este ejemplo, los gestores FileManager y DatabaseConnection se anidan dentro de la misma sentencia with. Esto permite abrir el archivo y establecer la conexión a la base de datos a la vez. Las operaciones posteriores de escritura y base de datos se realizan dentro de este contexto combinado.
Algo a tener en cuenta es la legibilidad del código. Te recomendaría no exceder dos contextos simultáneos.
Conclusión
Los gestores de contexto en Python ofrecen una forma estructurada de gestionar recursos dentro de una sentencia with, garantizando su correcta asignación y liberación.
A lo largo de este tutorial, hemos visto los fundamentos de los gestores de contexto, ejemplos prácticos y temas avanzados como el manejo de errores y el anidamiento. Al dominar la creación de gestores de contexto personalizados, podrás escribir código más limpio y fiable, mejorar el manejo de errores y gestionar recursos con eficiencia.
El tema de escribir gestores de contexto personalizados entra dentro de la categoría de «Python avanzado». Aquí tienes algunos recursos relacionados para seguir desarrollando tus habilidades:
Soy creador de contenidos sobre ciencia de datos con más de 2 años de experiencia y uno de los mayores seguimientos en Medium. Me gusta escribir artículos detallados sobre IA y ML con un toque sarcástico, porque hay que darle algo de vidilla al tema. He publicado más de 130 artículos y un curso en DataCamp, y tengo otro en marcha. Mis contenidos han sido vistos por más de 5 millones de personas; 20.000 de ellas se convirtieron en seguidores tanto en Medium como en LinkedIn.
Esta guía concisa y fácil de seguir te ayudará a descubrir las mejores alternativas a Anaconda y a encontrar la herramienta adecuada para tus proyectos en Python.
Domina los exponentes en Python utilizando diversos métodos, desde funciones integradas hasta potentes bibliotecas como NumPy, y aprovéchalos en situaciones reales para profundizar en su comprensión.
Aprende qué son los ámbitos de las variables y familiarízate con la regla «LEGB». También te encontrarás con situaciones en las que podrás ver las palabras clave globales y no locales en acción.
Mejora tus conocimientos de programación. Aprende a optimizar el código, a escribir funciones y pruebas, y a utilizar las mejores técnicas de ingeniería de software.
Motivación
Puede que ya conozcas la sentencia
with, una forma concisa de gestionar recursos en Python. Pero, ¿te has preguntado alguna vez cómo funciona por dentro? La fuerza de la palabra clavewithviene de los gestores de contexto.Los gestores de contexto son un patrón de diseño fundamental en Python que aporta una forma estructurada de gestionar recursos. Garantizan que los recursos se adquieran, se usen correctamente y, por último, se liberen o limpien, incluso cuando hay errores o excepciones.
Esto es especialmente importante al trabajar con recursos como ficheros, conexiones de red o manejadores de bases de datos. Gracias a los gestores de contexto, podemos escribir código más limpio y fiable, sin preocuparnos por olvidar cerrar un archivo o liberar un bloqueo.
En este tutorial, iremos más allá de los gestores de contexto que ofrece Python por defecto y aprenderemos a escribir los nuestros.
Entender los gestores de contexto en Python
Bajo el capó, los gestores de contexto son objetos que definen dos métodos especiales:
__enter__y__exit__. El método__enter__se llama al entrar en el bloque with y su valor de retorno se asigna a una variable dentro de ese bloque. El método__exit__, por su parte, se llama cuando se sale del bloquewith, tanto si termina con normalidad como si lo hace con una excepción.Esta estructura garantiza un manejo correcto de los recursos. Veamos algunos gestores de contexto integrados en Python para entenderlo mejor:
1. Gestión de archivos
Tomemos el ejemplo clásico de abrir un archivo:
Aquí,
open('file.txt', 'r')actúa como gestor de contexto. Al entrar en el bloquewith, se llama al método enter del objeto archivo, se abre el fichero y se asigna a la variable file. Después puedes usarfile.read()para acceder a su contenido.A continuación, se garantiza que el método
__exit__del objeto archivo se llame al salir del bloquewith, incluso si se produce una excepción. Este método se encarga de cerrar el archivo, evitando dejar descriptores abiertos por ahí.2. Bloqueo de hilos
Más allá de los archivos, los gestores de contexto también pueden usarse para la sincronización de hilos con
threading.Lock():Aquí,
lockes un objetothreading.Lock, otro gestor de contexto. Al entrar en el bloquewith, el método__enter__adquiere el bloqueo, garantizando que solo un hilo pueda ejecutar la sección crítica a la vez. Finalmente, el método__exit__libera el bloqueo al salir del bloquewith, permitiendo continuar a otros hilos.3. Conexiones a bases de datos
De forma similar, los gestores de contexto pueden gestionar conexiones a bases de datos:
La llamada
sqlite3.connect('database.db')es un gestor de contexto. Al entrar en el bloquewithse establece la conexión a la base de datos y se asigna aconnection. Después puedes usar uncursorpara interactuar con la base. El método__exit__garantiza que la conexión se cierre al salir del bloquewith, evitando fugas de recursos.4. Sockets de red
Los gestores de contexto incluso pueden encargarse de la comunicación de red:
Aquí,
socket.socket(socket.AF_INET, socket.SOCK_STREAM)crea un objeto socket que actúa como gestor de contexto. El método__enter__crea el socket y, dentro del bloquewith, puedes conectar, enviar y recibir datos. El método__exit__garantiza que el socket se cierre correctamente al finalizar.5. Exploración de directorios
En este caso,
os.scandir('.')permite iterar por las entradas de un directorio:os.scandir('.')actúa aquí como gestor de contexto. El método__enter__abre el escaneo del directorio y puedes iterar por las entradas dentro del bloquewith. El método__exit__limpia el escaneo al salir.Como ves, la sentencia
with, impulsada por los gestores de contexto, simplifica la gestión de recursos al encargarse automáticamente de su asignación y liberación.Crear gestores de contexto personalizados en Python
Veamos ahora cómo escribir tus propios gestores para tener un control más fino sobre la gestión de recursos.
Hay dos enfoques principales para escribir gestores de contexto personalizados: basados en clases y basados en funciones.
Enfoque basado en clases
El enfoque basado en clases es el método más estructurado y flexible para escribir gestores de contexto. Aquí defines una clase que implementa los métodos especiales
__enter__y__exit__.Veamos un ejemplo de una clase
Timerque mide el tiempo de ejecución:Aquí, la clase
Timerdefine el método__enter__para capturar la hora de inicio al entrar en el bloque with. Devuelveselfpara permitir el acceso al objeto dentro del bloque. El método__exit__calcula el tiempo transcurrido al salir del bloquewithy lo imprime.Enfoque basado en funciones
Si prefieres algo más conciso, aunque quizá menos flexible, el enfoque basado en funciones puede ser una buena opción. Aquí usas el decorador
contextmanagerdel módulocontextlibpara convertir una función en gestor de contexto.Veamos cómo funciona:
El decorador
@contextmanagertransforma la función timer en un gestor de contexto. Dentro de la función se capturastart_time, y la sentenciayieldpausa la ejecución para que se ejecute el código del bloquewith.Por último, la funcionalidad equivalente a
__exit__se consigue capturando la hora final e imprimiendo el tiempo transcurrido.En esencia, escribes la lógica de
__enter__antes de la palabra claveyield, mientras que la lógica de__exit__va después. Ambos enfoques logran lo mismo; la elección depende de tu preferencia por la estructura y la legibilidad.Ejemplos prácticos de gestores de contexto
Ahora que sabes escribir gestores de contexto personalizados en Python, veamos algunos ejemplos prácticos donde pueden ser muy útiles.
Gestionar operaciones con archivos
Las operaciones con archivos son habituales en muchas aplicaciones. Ya sea leer o escribir, una buena gestión garantiza la integridad de los datos y la eficiencia de los recursos. Consideremos un escenario en el que queremos escribir texto a un archivo usando un gestor de contexto personalizado.
En este ejemplo, definimos una clase
FileManagerque imita la funciónopende Python y gestiona las operaciones con archivos. Desglosando cada método:__init__(self, filename, mode): es el constructor de la clase. Inicializa el objetoFileManagercon el nombre de archivo y el modo, que especifican qué archivo abrir y en qué modo (por ejemplo, lectura, escritura, anexar).__enter__(self): se llama al entrar en el bloquewith. Abre el archivo indicado porfilenameen el modo indicado pormode. El objeto fichero abierto se asigna aself.filey se devuelve para usarse dentro del bloquewith.__exit__(self, exc_type, exc_value, traceback): se llama al salir del bloque with, tanto si se produjo una excepción como si no. Garantiza que el archivo se cierre correctamente llamando aself.file.close()siself.fileno esNone. Así se evitan fugas de recursos y se asegura la limpieza.Si inspeccionas el contenido de
example.txttras ejecutar el código anterior, verás el texto escrito:Por supuesto, la ventaja de la clase
FileManageres que puedes implementar cualquier lógica personalizada para trabajar con archivos. Por ejemplo, puedes modificarla para que lleve un registro en un fichero de texto de qué archivos se abren o cierran.En esta versión modificada:
datetimepara trabajar con marcas de tiempo.log_actionpara registrar acciones sobre archivos.log_filenamepara indicar el nombre del archivo de registro. El valor por defecto es'file_log.txt'.log_actiondentro de los métodos__enter__y__exit__.log_action, se usadatetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")para obtener la marca temporal en el formato"YYYY-MM-DD HH:MM:SS".Ahora, si imprimimos el contenido de
file_log.txt, veremos los registros:Otro caso de uso práctico que podemos implementar como gestor de contexto personalizado es una herramienta de gestión de bases de datos SQLite:
De nuevo, esto imita la función
sqlite3.connect, pero puede mejorarse añadiendo lógica personalizada de gestión de la base de datos. Comprobemos si el gestor funciona con algunas funciones de ejemplo:Podemos escribir un código mucho más mantenible separando las operaciones de base de datos en funciones y usando el gestor personalizado que acabamos de crear.
Temas avanzados sobre gestores de contexto en Python
En esta sección, hablaremos de temas avanzados relacionados con los gestores de contexto en Python. Entre ellos, el manejo de errores y el anidamiento de gestores de contexto.
Manejo de errores
El manejo de errores es esencial en programación, y los gestores de contexto en Python facilitan gestionar errores dentro de operaciones de gestión de recursos.
En el ejemplo de la clase FileManager, el manejo de errores puede implementarse dentro del método
__exit__para asegurar la limpieza incluso si ocurre una excepción. Por ejemplo, si se produce un error al escribir en el archivo (dentro del bloquewith), aun así queremos asegurarnos de que el archivo se cierra para evitar fugas de recursos. Podemos modificar__exit__así:Aquí, primero cerramos el archivo con
self.file.close()para asegurar la limpieza. Luego comprobamos si ocurrió una excepción(exc_type is not None). Si es así, imprimimos un mensaje de error para dar contexto de lo sucedido.Aquí:
exc_typees la clase de la excepción, comoAttributeErroroIndexError.exc_valuees la instancia de la excepción con su mensaje.tracebackes el traceback completo del error.Ejecutemos la clase
FileManagercon un código incorrecto a propósito:Así, para implementar lógica personalizada al manejar excepciones en tus gestores, aquí tienes un flujo de trabajo de ejemplo que puedes seguir:
Anidar gestores de contexto
Anidar gestores de contexto te permite gestionar varios recursos a la vez, cada uno con su propio gestor, dentro de una sola sentencia
with. Esto es especialmente útil en operaciones complejas que implican múltiples recursos. Veamos cómo anidarlos en nuestros ejemplos.Imagina que quieres abrir un archivo y realizar operaciones de base de datos dentro del mismo contexto. Por ejemplo, introducir el contenido de un CSV como filas de una base de datos. Podemos conseguirlo anidando los gestores
FileManageryDatabaseConnectiondentro de una sola sentenciawith:En este ejemplo, los gestores FileManager y DatabaseConnection se anidan dentro de la misma sentencia
with. Esto permite abrir el archivo y establecer la conexión a la base de datos a la vez. Las operaciones posteriores de escritura y base de datos se realizan dentro de este contexto combinado.Algo a tener en cuenta es la legibilidad del código. Te recomendaría no exceder dos contextos simultáneos.
Conclusión
Los gestores de contexto en Python ofrecen una forma estructurada de gestionar recursos dentro de una sentencia
with, garantizando su correcta asignación y liberación.A lo largo de este tutorial, hemos visto los fundamentos de los gestores de contexto, ejemplos prácticos y temas avanzados como el manejo de errores y el anidamiento. Al dominar la creación de gestores de contexto personalizados, podrás escribir código más limpio y fiable, mejorar el manejo de errores y gestionar recursos con eficiencia.
El tema de escribir gestores de contexto personalizados entra dentro de la categoría de «Python avanzado». Aquí tienes algunos recursos relacionados para seguir desarrollando tus habilidades: