Encontrei a with
instrução Python pela primeira vez hoje. Estou usando o Python de ânimo leve há vários meses e nem sabia de sua existência! Dado seu status um tanto obscuro, pensei que valeria a pena perguntar:
- Para que a
with
instrução Python foi projetada para ser usada? - para que você usa isso?
- Existem algumas dicas que eu preciso estar ciente ou anti-padrões comuns associados ao seu uso? Algum caso em que é melhor usar do
try..finally
quewith
? - Por que não é usado mais amplamente?
- Quais classes de biblioteca padrão são compatíveis com ele?
with
na documentação do Python 3.Respostas:
Acredito que isso já tenha sido respondido por outros usuários antes de mim, portanto, apenas o adiciono por questões de integridade: a
with
instrução simplifica o tratamento de exceções, encapsulando tarefas comuns de preparação e limpeza nos chamados gerenciadores de contexto . Mais detalhes podem ser encontrados no PEP 343 . Por exemplo, aopen
instrução é um gerenciador de contexto em si, que permite abrir um arquivo, mantê-lo aberto enquanto a execução estiver no contexto dawith
instrução em que você o usou e fechá-lo assim que sair do contexto, não importa se você o deixou devido a uma exceção ou durante o fluxo de controle regular. Awith
instrução pode, portanto, ser usada de maneiras semelhantes ao padrão RAII em C ++: algum recurso é adquirido pelowith
e liberada quando você sai dowith
contexto.Alguns exemplos são: abrir arquivos usando
with open(filename) as fp:
, adquirindo bloqueios usandowith lock:
(ondelock
é uma instância dethreading.Lock
). Você também pode construir seus próprios gerenciadores de contexto usando ocontextmanager
decorador decontextlib
. Por exemplo, costumo usar isso quando preciso alterar temporariamente o diretório atual e depois retornar para onde estava:Aqui está outro exemplo que redireciona temporariamente
sys.stdin
,sys.stdout
esys.stderr
para algum outro identificador de arquivo e restaura-los mais tarde:E, finalmente, outro exemplo que cria uma pasta temporária e a limpa ao sair do contexto:
fonte
with
instrução foi criada para preencher uma variável com dados até que as instruções contidas nela estejam completas e liberar a variável?with open('myScript.py', 'r') as f: pass
. Eu esperava ser capaz de chamar a variávelf
para ver o conteúdo do texto do documento, como este é o que apareceria se o documento foram atribuídos af
via regularopen
declaração:f = open('myScript.py').read()
. Mas em vez disso eu tenho o seguinte:<_io.TextIOWrapper name='myScript.py' mode='r' encoding='cp1252'>
. O que isso significa?with
não remove a necessidaderead
do arquivo real. Aswith
chamadasopen
- não sabe o que você precisa fazer com ela - você pode querer procurar, por exemplo.with
declaração pode preencher uma variável com dados ou fazer alguma outra alteração no ambiente até que as instruções contidas nela estejam completas e, em seguida, faça qualquer tipo de limpeza necessária. Os tipos de limpeza que podem ser feitos são como fechar um arquivo aberto ou, como o @Tamas fez neste exemplo, alterar os diretórios de volta para onde você estava antes, etc. Como o Python tem coleta de lixo, liberar uma variável não é importante. caso de uso.with
é geralmente usado para outros tipos de limpeza.Eu sugeriria duas palestras interessantes:
1. A
with
instrução é usada para agrupar a execução de um bloco com métodos definidos por um gerenciador de contexto. Isso permite quetry...except...finally
padrões de uso comuns sejam encapsulados para reutilização conveniente.2. Você pode fazer algo como:
OU
OR (Python 3.1)
OU
3. Não vejo nenhum antipadrão aqui.
Citando o Mergulho no Python :
4. Acho que está relacionado ao hábito dos programadores de usar
try..catch..finally
declarações de outros idiomas.fonte
with
.A
with
instrução Python é o suporte àResource Acquisition Is Initialization
linguagem interna do idioma comumente usado em C ++. Destina-se a permitir a aquisição e liberação seguras de recursos do sistema operacional.A
with
instrução cria recursos dentro de um escopo / bloco. Você escreve seu código usando os recursos dentro do bloco. Quando o bloco sai, os recursos são liberados corretamente, independentemente do resultado do código no bloco (ou seja, se o bloco sai normalmente ou devido a uma exceção).Muitos recursos da biblioteca Python que obedecem ao protocolo exigido pela
with
instrução e, portanto, podem ser usados com ela imediatamente. No entanto, qualquer pessoa pode criar recursos que possam ser usados em uma declaração with, implementando o protocolo bem documentado: PEP 0343Use-o sempre que você adquirir recursos em seu aplicativo que devam ser explicitamente abandonados, como arquivos, conexões de rede, bloqueios e similares.
fonte
Novamente, para completar, adicionarei meu caso de uso mais útil para
with
instruções.Faço muita computação científica e, para algumas atividades, preciso da
Decimal
biblioteca para cálculos de precisão arbitrários. Alguma parte do meu código eu preciso de alta precisão e para a maioria das outras partes eu preciso de menos precisão.Defino minha precisão padrão como um número baixo e, em seguida, uso
with
para obter uma resposta mais precisa para algumas seções:Eu uso muito isso com o Teste Hipergeométrico, que requer a divisão de grandes números resultantes de fatores fatoriais. Ao fazer cálculos de escala genômica, você deve ter cuidado com os erros de arredondamento e transbordamento.
fonte
Um exemplo de um antipadrão pode ser o uso de
with
um loop interno, quando seria mais eficiente ter owith
exterior do looppor exemplo
vs
A primeira maneira é abrir e fechar o arquivo para cada um deles, o
row
que pode causar problemas de desempenho em comparação com a segunda maneira com abrir e fechar o arquivo apenas uma vez.fonte
Veja PEP 343 - A declaração 'with' , há uma seção de exemplo no final.
fonte
1, 2 e 3, sendo razoavelmente bem cobertos:
4: é relativamente novo, disponível apenas em python2.6 + (ou python2.5 usando
from __future__ import with_statement
)fonte
A instrução with funciona com os chamados gerenciadores de contexto:
http://docs.python.org/release/2.5.2/lib/typecontextmanager.html
A idéia é simplificar o tratamento de exceções, fazendo a limpeza necessária depois de sair do bloco 'with'. Alguns dos python internos já funcionam como gerenciadores de contexto.
fonte
Outro exemplo de suporte pronto para uso, e um que pode ser um pouco desconcertante no início quando você está acostumado com o
open()
comportamento interno, sãoconnection
objetos de módulos populares de banco de dados, como:Os
connection
objetos são gerenciadores de contexto e, como tal, podem ser usados imediatamente em awith-statement
, no entanto, ao usar a nota acima, observe que:Isso significa que o programador deve cuidar de fechar a conexão, mas permite adquirir uma conexão e usá-la em múltiplos
with-statements
, conforme mostrado nos documentos do psycopg2 :No exemplo acima, você observará que os
cursor
objetospsycopg2
também são gerenciadores de contexto. A partir da documentação relevante sobre o comportamento:fonte
No python, geralmente a instrução " with " é usada para abrir um arquivo, processar os dados presentes no arquivo e também para fechar o arquivo sem chamar um método close (). A declaração "with" simplifica o tratamento de exceções, fornecendo atividades de limpeza.
Forma geral de com:
note: não é necessário fechar o arquivo chamando close () no arquivo-var.close ()
fonte