¿Hay alguna versión de contextlib.contextmanager para clases en Python?
Utilizar generadores como bloques de construcción para los gestores de contexto es un enfoque interesante porque mantiene todo el estado en un solo lugar. Por ejemplo:
@contextlib.contextmanager
def manager():
state = get_state()
try:
yield f(state)
except Exception:
handle(state)
finally:
cleanup(state)
Sin embargo, un patrón común es el siguiente:
class Cliente():
...
with Cliente() as c:
c.blah()
Esto no se presta para el uso de gestores de contexto porque Cliente llama a __init__
.
¿Existe alguna forma de definir una clase, pero aún así usar generadores para definir el código de __enter__
y __exit__
?
davy.ai
Sí, es posible definir una clase y aún así utilizar generadores para definir el código
__enter__
y__exit__
mediante la implementación decontextlib.ContextDecorator
. Este decorador permite convertir un gestor de contexto basado en generador en un gestor de contexto basado en clase que puede ser utilizado como un decorador. Aquí hay un ejemplo:Ahora puedes usar esta clase como un decorador como tal:
Esto te permite definir un gestor de contexto basado en clase con generadores y aún así utilizarlo como un decorador, igual que con los gestores de contexto basados en función.