Gerenciadores de contexto Python

Resumo : neste tutorial, você aprenderá sobre os gerenciadores de contexto Python e como usá-los de forma eficaz

Introdução aos gerenciadores de contexto Python

Um gerenciador de contexto é um objeto que define um contexto de tempo de execução em execução na withinstrução.

Vamos começar com um exemplo simples para entender o conceito de gerenciador de contexto.

Suponha que você tenha um arquivo chamado data.txtque contém um número inteiro 100 .

O programa a seguir o data.txtarquivo, converte seu conteúdo em um número e mostra o resultado na saída padrão:

f = open('data.txt')
data = f.readlines()

# convert the number to integer and display it
print(int(data[0]))

f.close()Linguagem de código:  Python  ( python )

O código é simples e direto.

No entanto, data.txtpode conter dados que não podem ser convertidos em um número. Nesse caso, o código resultará em uma exceção.

Por exemplo, se data.txtcontiver a string '100'em vez do número 100, você receberá o seguinte erro:

ValueError: invalid literal for int() with base 10: "'100'"Linguagem de código:  Python  ( python )

Devido a esta exceção, o Python pode não fechar o arquivo corretamente.

Para corrigir isso, você pode usar a try...except...finally instrução:

try:
    f = open('data.txt')
    data = f.readlines()
    # convert the number to integer and display it
    print(int(data[0]))
except ValueError as error:
    print(error)
finally:
    f.close()Linguagem de código:  Python  ( python )

Como o código no finallybloco sempre é executado, o código sempre fechará o arquivo corretamente.

Esta solução funciona conforme o esperado. No entanto, é bastante detalhado.

Portanto, Python fornece uma maneira melhor que permite fechar automaticamente o arquivo após concluir o processamento.

É aqui que entram em jogo os gerenciadores de contexto .

A seguir mostramos como usar um gerenciador de contexto para processar o data.txtarquivo:

with open('data.txt') as f:
    data = f.readlines()
    print(int(data[0])    
Linguagem de código:  Python  ( python )

Neste exemplo, usamos a open()função com a withinstrução. Após o withbloco, o Python será fechado automaticamente.

withInstrução Python

Aqui está a sintaxe típica da withinstrução:

with context as ctx:
    # use the the object 

# context is cleaned upLinguagem de código:  Python  ( python )

Como funciona.

  • Quando Python encontra a withinstrução, ele cria um novo contexto. O contexto pode opcionalmente retornar um arquivo object.
  • Após o withbloco, o Python limpa o contexto automaticamente.
  • O escopo do ctxtem o mesmo escopo da withdeclaração. Isso significa que você pode acessar ctxdentro e depois da withinstrução.

O seguinte mostra como acessar a fvariável após a withinstrução:

with open('data.txt') as f:
    data = f.readlines()
    print(int(data[0]))


print(f.closed)  # TrueLinguagem de código:  Python  ( python )

Protocolo gerenciador de contexto Python

Os gerenciadores de contexto Python funcionam com base no protocolo do gerenciador de contexto .

O protocolo gerenciador de contexto possui os seguintes métodos:

  • __enter__()– configure o contexto e opcionalmente retorne algum objeto
  • __exit__()– limpe o objeto.

Se você deseja que uma classe suporte o protocolo do gerenciador de contexto, você precisa implementar esses dois métodos.

Suponha que ContextManagerseja uma classe que suporta o protocolo do gerenciador de contexto.

A seguir mostramos como usar a ContextManagerclasse:

with ContextManager() as ctx:
    # do something
# done with the contextLinguagem de código:  Python  ( python )

Quando você usa ContextManagerclass com a withinstrução, Python cria implicitamente uma instância da ContextManagerclasse ( instance) e chama automaticamente __enter__()o método nessa instância.

O __enter__()método pode opcionalmente retornar um objeto. Nesse caso, o Python atribui ao objeto retornado o ctx.

Observe que isso ctxfaz referência ao objeto retornado pelo __enter__()método. Não faz referência à instância da ContextManagerclasse.

Se ocorrer uma exceção dentro do bloco with ou após o withbloco, o Python chama o __exit__()método no instanceobjeto.

Gerenciadores de contexto Python

Funcionalmente, a withdeclaração é equivalente à seguinte try...finallydeclaração:

   instance = ContextManager()
ctx = instance.__enter__()

try:
    # do something with the txt
finally:
    # done with the context
    instance.__exit__()
Linguagem de código:  Python  ( python )

O método __enter__()

No __enter__()método, você pode realizar as etapas necessárias para configurar o contexto.

Opcionalmente, você pode retornar um objeto do __enter__()método.

O método __exit__()

Python sempre executa o __exit__()método mesmo se ocorrer uma exceção no withbloco.

O __exit__()método aceita três argumentos: tipo de exceção, valor de exceção e objeto de rastreamento. Todos esses argumentos serão válidos Nonese nenhuma exceção ocorrer.

def __exit__(self, ex_type, ex_value, ex_traceback):
    ...Linguagem de código:  Python  ( python )

O __exit__()método retorna um valor booleano, Trueou False.

Se o valor de retorno for True, o Python tornará qualquer exceção silenciosa. Caso contrário, não silencia a exceção.

Aplicativos gerenciadores de contexto Python

Como você pode ver no exemplo anterior, o uso comum de um gerenciador de contexto é abrir e fechar arquivos automaticamente.

No entanto, você pode usar gerenciadores de contexto em muitos outros casos:

1) Abrir – Fechar

Se quiser abrir e fechar um recurso automaticamente, você pode usar um gerenciador de contexto.

Por exemplo, você pode abrir um soquete e fechá-lo usando um gerenciador de contexto.

2) Bloquear – liberar

Os gerenciadores de contexto podem ajudá-lo a gerenciar bloqueios de objetos de maneira mais eficaz. Eles permitem que você adquira um bloqueio e libere-o automaticamente.

3) Iniciar – parar

Os gerenciadores de contexto também ajudam você a trabalhar com um cenário que requer as fases de início e parada.

Por exemplo, você pode usar um gerenciador de contexto para iniciar um cronômetro e pará-lo automaticamente.

3) Alterar – redefinir

Os gerenciadores de contexto podem trabalhar com cenários de mudança e redefinição.

Por exemplo, seu aplicativo precisa se conectar a diversas fontes de dados. E tem uma conexão padrão.

Para se conectar a outra fonte de dados:

  • Primeiro, use um gerenciador de contexto para alterar a conexão padrão para uma nova.
  • Segundo, trabalhe com a nova conexão
  • Terceiro, redefina-o para a conexão padrão assim que terminar de trabalhar com a nova conexão.

Implementando o protocolo gerenciador de contexto Python

O seguinte mostra uma implementação simples da open()função usando o protocolo do gerenciador de contexto:

class File:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        print(f'Opening the file {self.filename}.')
        self.__file = open(self.filename, self.mode)
        return self.__file

    def __exit__(self, exc_type, exc_value, exc_traceback):
        print(f'Closing the file {self.filename}.')
        if not self.__file.closed:
            self.__file.close()

        return False


with File('data.txt', 'r') as f:
    print(int(next(f)))
Linguagem de código:  Python  ( python )

Como funciona.

  • Primeiro, inicialize o filenamee modeno __init__()método.
  • Segundo, abra o arquivo no __enter__()método e retorne o objeto de arquivo.
  • Terceiro, feche o arquivo se estiver aberto no __exit__()método.

Usando o gerenciador de contexto Python para implementar o padrão de início e parada

O seguinte define uma Timerclasse que suporta o protocolo do gerenciador de contexto:

from time import perf_counter


class Timer:
    def __init__(self):
        self.elapsed = 0

    def __enter__(self):
        self.start = perf_counter()
        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.stop = perf_counter()
        self.elapsed = self.stop - self.start
        return False
Linguagem de código:  Python  ( python )

Como funciona.

  • Primeiro, importe o arquivo perf_counterdo timemódulo.
  • Segundo, inicie o cronômetro no __enter__()método
  • Terceiro, pare o cronômetro no __exit__()método e retorne o tempo decorrido.

Agora você pode usar a Timerclasse para medir o tempo necessário para calcular o Fibonacci de 1000, um milhão de vezes:

def fibonacci(n):
    f1 = 1
    f2 = 1
    for i in range(n-1):
        f1, f2 = f2, f1 + f2

    return f1


with Timer() as timer:
    for _ in range(1, 1000000):
        fibonacci(1000)

print(timer.elapsed)Linguagem de código:  Python  ( python )

Resumo

  • Use gerenciadores de contexto Python para definir contextos de tempo de execução ao executar a withinstrução.
  • implementar os métodos __enter__()e __exit__()para suportar o protocolo do gerenciador de contexto.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *