2.24. Gestores de contexto¶
A instrução with executa código de configuração, depois um corpo, depois código de limpeza – com a garantia de que a limpeza é executada mesmo quando o corpo falha a meio. O par de métodos que fornece a configuração e a limpeza chama-se gestor de contexto.
A forma é:
with <expression> as <name>:
<body>
A expressão devolve um gestor de contexto. O Python chama o seu método __enter__, opcionalmente associa o resultado a <name>, executa o corpo e depois chama __exit__ – quer o corpo tenha terminado normalmente ou levantado uma excepção.
__exit__ é executado no final do bloco independentemente do que aconteça dentro dele.¶
2.24.1. Utilizar um gestor de contexto¶
O exemplo canónico é abrir um ficheiro:
with open("data.txt") as f:
text = f.read()
# f is now closed, even if read() failed
open() devolve um objecto de ficheiro que é em si mesmo um gestor de contexto; __enter__ devolve o ficheiro e __exit__ fecha-o. O bloco with torna «fechar sempre o ficheiro quando terminar» o comportamento por omissão em vez de algo que o invocador tem de se lembrar de fazer.
2.24.1.1. Múltiplos gestores de contexto¶
Uma única instrução with pode entrar em vários gestores de contexto ao mesmo tempo, separados por vírgulas:
with open("input.txt") as src, open("output.txt", "w") as dst:
dst.write(src.read())
Equivalente a dois blocos with aninhados, mas mais plano. Os gestores são entrados da esquerda para a direita e saídos na ordem inversa; se __enter__ no gestor do lado direito lançar uma excepção, o __exit__ do gestor do lado esquerdo ainda é executado.
2.24.2. Escrever um gestor de contexto¶
Qualquer classe com os métodos __enter__ e __exit__ funciona como gestor de contexto:
class Section:
def __init__(self, label):
self.label = label
def __enter__(self):
print("---", self.label, "---")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("--- end", self.label, "---")
return False
with Section("setup"):
print("doing the work")
Resultado:
--- setup ---
doing the work
--- end setup ---
__exit__ recebe três argumentos que descrevem a excepção que terminou o bloco, ou três valores None se o bloco terminou normalmente. Devolver False (ou None) permite que qualquer excepção se propague após a limpeza; devolver True suprimiria a excepção.
Use gestores de contexto para qualquer recurso com um ciclo de vida «abrir / fechar» ou «adquirir / libertar» – não apenas ficheiros. O padrão mantém a limpeza emparelhada com a configuração no ponto em que ambas são introduzidas, de modo que um fecho esquecido no meio de uma função longa não pode causar fuga do recurso.