Para que é a declaração Python "com" usada?
Pergunta
Estou tentando entender a declaração com Python. Em todos os lugares que eu olho, fala sobre abrir e fechar um arquivo, e deve substituir o bloqueio Try-Finally. Alguém poderia postar outros exemplos também. Estou apenas experimentando frasco e há com declarações em abundância. Definitivamente, solicite alguém para fornecer alguma clareza sobre isso.
Solução
Há uma explicação muito boa aqui. Basicamente, a declaração com a declaração chama dois métodos especiais no objeto associado. Os métodos __enter__ e __Exit__. O método Enter retorna a variável associada à instrução "com". Enquanto o método __Exit__ é chamado após a declaração executar para lidar com qualquer limpeza (como fechar um ponteiro de arquivo).
Outras dicas
A ideia do with
A declaração é fazer "fazer a coisa certa" o caminho da menor resistência. Embora o exemplo do arquivo seja o mais simples, os bloqueios de encadeamento fornecem um exemplo mais clássico de código de buggy não obviamente:
try:
lock.acquire()
# do stuff
finally:
lock.release()
Este código está quebrado - se a aquisição de bloqueio falhar, a exceção errada será lançada (como o código tentará liberar uma fechadura que nunca adquiriu) ou, pior, se for uma trava recursiva, será liberada cedo. O código correto se parece com o seguinte:
lock.acquire()
try:
# do stuff
finally:
# If lock.acquire() fails, this *doesn't* run
lock.release()
Usando a with
Declaração, torna -se impossível errar, pois está incorporado ao gerente de contexto:
with lock: # The lock *knows* how to correctly handle acquisition and release
# do stuff
O outro lugar onde o with
A declaração ajuda muito é semelhante ao principal benefício da função e dos decoradores de classe: é preciso o código "duas peças", que pode ser separado por um número arbitrário de linhas de código (a definição de função para os decoradores, o try
bloco no caso atual) e o transforma em código "One Piece", onde o programador simplesmente declara na frente o que eles estão tentando fazer.
Para exemplos curtos, isso não parece um grande ganho, mas na verdade faz uma enorme diferença ao revisar o código. Quando eu vejo lock.acquire()
Em um pedaço de código, preciso rolar para baixo e verificar se há um correspondente lock.release()
. Quando eu vejo with lock:
, porém, essa verificação é necessária - posso ver imediatamente que o bloqueio será lançado corretamente.
Existem doze exemplos de uso with
dentro PEP343, incluindo o exemplo de abertura:
- Um modelo para garantir que um bloqueio, adquirido no início de um bloco, seja liberado quando o bloco for deixado
- Um modelo para abrir um arquivo que garante que o arquivo seja fechado quando o bloco é deixado
- Um modelo para cometer ou reverter uma transação de banco de dados
- Exemplo 1 reescrito sem um gerador
- Redirecionar o stdout temporariamente
- Uma variante no aberto () que também retorna uma condição de erro
- Outro exemplo útil seria uma operação que bloqueia os sinais
- Outro uso para esse recurso é o contexto decimal
- Aqui está um gerente de contexto simples para o módulo decimal
- Um gerente de contexto genérico de "fechamento de objetos"
- Um contexto liberado () para liberar temporariamente um bloqueio adquirido anteriormente trocando as chamadas adquiridas () e liberação ()
- Um gerente de contexto "aninhado" que aninha automaticamente os contextos fornecidos da esquerda para a direita para evitar o indentação excessiva